Repository navigation
Expand file tree
/
Copy pathcontinuous-integration.html
More file actions
256 lines (256 loc) · 31.3 KB
/
Copy pathcontinuous-integration.html
File metadata and controls
256 lines (256 loc) · 31.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="author" content="Matt Makai">
<meta name="description" content="当开发者们提交代码时,持续集成(CI)会自动重新构建、测试并部署应用。">
<title>持续集成 - Full Stack Python</title>
<link href="/f.css" rel="stylesheet">
<link rel="shortcut icon" href="/img/fsp-fav.png">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12">
<div class="logo-header-section">
<a href="/" style="text-decoration: none; border: none;"><img src="/img/logo-sm.png" class="logo-image" alt="Full Stack Python logo"></a>
<span class="logo-title"><a href="https://www.fullstackpython.com/">Full Stack Python</a></span>
</div>
<div class="sans-font">
<!--<a href="/blog.html" class="submenu-item-first">Blog</a> |
<a href="/books.html" class="submenu-item">Books</a> | -->
<a href="/table-of-contents.html">全部主题</a>
<span style="margin:0 12px 0 12px">|</span>
<a href="/blog.html">Blog</a>
<span style="margin:0 12px 0 12px">|</span>
<a href="/email.html">时讯</a>
<span style="margin:0 12px 0 12px">|</span>
<a href="https://twitter.com/fullstackpython">@fullstackpython</a>
<span style="margin:0 12px 0 12px">|</span>
<a href="https://www.facebook.com/fullstackpython">Facebook</a>
<span style="margin:0 12px 0 12px">|</span>
<a href="https://github.com/mattmakai/fullstackpython.com">源码</a>
</div> </div>
</div><div class="row">
<div class="col-md-8">
<h1>持续集成</h1>
<p>持续集成可以让构建、测试和部署应用自动完成。不管是由个人还是整个团队创建的软件项目,通常都会以持续集成为中心,来确保重要的步骤(如单元测试)都自动化完成了,而不是用手工处理。</p>
<h2>持续集成为何重要?</h2>
<p>当把持续继承(CI)作为软件项目开发过程中的一个步骤后,就可以大大减少部署时间,因为持续集成将那些需要人工干预的步骤次数最小化了。使用 CI 的小缺点有两处:第一,开发者需要花费一定的时间进行初始化设置;第二,如果一个项目被拆分成了多个部分,比如从单一架构到 <a href="/microservices.html">微服务</a> 架构,就会有一些不间断的维护工作。</p>
<h2>自动化测试</h2>
<p>使用 CI 的另外一个主要的优势是测试可以在部署过程中自动完成。
当开发者们检查源码库中的代码时,可以通过运行一个综合的测试套件 <a href="/unit-testing.html">unit</a> 和
<a href="/integration-testing.html">集成测试</a> 来防止部署受损的问题发生。在检查期间,任何由测试套件捕获的偶然出现的 bug 都会报告出来,从而阻止部署过程继续。</p>
<p>源码审查中的自动化测试就像是保龄球保险杠,可以防止代码质量偏离正规。整合了单元和集成测试的 CI 可以保证任何代码修改都不会破坏现有的测试,从而确保软件能够按照预期工作。</p>
<h2>持续集成的例子</h2>
<p>下面的这幅图片从更高的层面说明了持续集成和部署是如何工作的。</p>
<p><img src="/img/continuous-integration.png" width="100%" class="technical-diagram" alt="One potential way for continuous integration to work with source control and a deployment environment." /></p>
<p>如上图所示,当新的代码合并到源码库后,就会触发一个钩子来通知持续集成服务器有新的代码需要构建(如果通知功能不可用,持续集成服务器也可以采用轮询代码库的方式)。</p>
<p>持续集成服务器会获取到代码然后构建并测试。如果所有的测试都通过了,持续集成服务器就开始部署过程。新的代码会被同步到正在进行部署操作的服务器上。最后,通过重启服务以及相关的部署活动后,便完成了部署过程。</p>
<p>持续集成服务器和部署还有其它的结构图,以上仅是一种设置相对简单的例子。</p>
<h2>开源持续集成(CI)项目</h2>
<p>有很多种可以根据需要进行配置的免费开源持续集成服务器。</p>
<p>需要注意的是,其中有很多服务器都不是用 Python 实现的,但是可以很好地与 Python 应用配合使用。Polyglot 组织(使用超过一种语言和生态系统的组织)经常为他们的项目使用单一的集成服务器,而不管这些项目是用什么语言实现的。</p>
<ul>
<li>
<p><a href="http://jenkins-ci.org/">Jenkins</a> 是一个常见的 CI 服务器,用于在测试和生产服务器上构建并部署。
<a href="https://github.com/jenkinsci/jenkins">Jenkins 在 GitHub 上的源码库</a>。</p>
</li>
<li>
<p><a href="http://www.go.cd/">Go CD</a> 是由
<a href="http://www.thoughtworks.com/">ThoughtWorks</a> 打造的 CI 服务器,设计采用了针对构建、测试和发行周期的最佳实践。
<a href="https://github.com/gocd/gocd">Go CD 在 GitHub 上的源码库</a>。</p>
</li>
<li>
<p><a href="http://stridercd.com/">Strider</a> 是使用 node.js 编写的 CI 服务器。
<a href="https://github.com/Strider-CD/strider">Strider 在 GitHub 上的源码库</a>。</p>
</li>
<li>
<p><a href="http://buildbot.net/">BuildBot</a> 是一个持续集成 <strong>框架</strong>,含有一个用于创建你自己的 CI 服务器的组件集合。它使用 Python 来实现,并专为那些在构建和部署流水线中需要更多控制的开发团队打造。
<a href="https://github.com/buildbot/buildbot">BuildBot 在 GitHub 上的源码库</a>。</p>
</li>
<li>
<p><a href="https://www.jetbrains.com/teamcity/">TeamCity</a> 是 JetBrains' 的闭源
CI 服务器,它需要一个许可证才可以使用。</p>
</li>
</ul>
<h2>Jenkins CI 相关的资源</h2>
<ul>
<li>
<p><a href="https://medium.com/@mondaini/assembling-a-continuous-integration-service-for-a-django-project-on-jenkins-5f979d4c4184">用 Jenkins 为 Django 项目添加一个持续集成服务</a>
说明了如何为一个含有 Jenkins 服务器的 Ubuntu 实例进行设置,并使用 Jenkins 服务器构建一个 <a href="/django.html">Django</a> 项目。</p>
</li>
<li>
<p>我写的 <a href="http://www.deploypython.com/">部署 Python web 应用</a> 一书中详细讲解了设置一个 Jenkins 项目(含有一个 WSGI 应用)并实现持续交付的每一个步骤。如果你对其它博客中列出的所有步骤还不够了解的话,可以去看看那本书。</p>
</li>
<li>
<p><a href="http://michal.karzynski.pl/blog/2014/04/19/continuous-integration-server-for-django-using-jenkins/">将 Jenkins 设置为 Django 的持续集成服务器</a>
是另外一篇不错的教程,它说明了如何将发送邮件通知集成到构建过程中。 </p>
</li>
<li>
<p>如果你在向你的 Jenkins 系统账户中添加用于连接另外一个服务器或 Git 仓库的 SSH 秘钥时遇到困难的话,
<a href="http://dcycleproject.org/blog/51/connecting-jenkins-and-git">这篇让 Jenkins 和 Git 连接的博客</a>
会告诉你解决问题的步骤。</p>
</li>
<li>
<p><a href="http://chromaticsites.com/blog/automated-servers-and-deployments-ansible-jenkins">使用 Ansible 和 Jenkins 实现自动化服务器和部署</a>。</p>
</li>
<li>
<p><a href="http://www.catosplace.net/blog/2015/02/11/running-jenkins-in-docker-containers/">在 Docker 容器中运行 Jenkins</a>
是一个简短的教程说明了如何在 Docker hub 中使用官方的
<a href="https://registry.hub.docker.com/_/jenkins/">Jenkins 容器</a>。</p>
</li>
<li>
<p><a href="https://wiki.jenkins-ci.org/display/JENKINS/Securing+Jenkins">保护 Jenkins 的安全</a>
是 Jenkins 安全的登录页面。如果你正在部署你自己的实例,你需要给服务器加锁防止未授权的用户访问。</p>
</li>
<li>
<p><a href="http://engineering.simondata.com/can-we-use-jenkins-for-that">我们可以使用 Jenkins 做到吗?</a>
看看一个团队如何做到将 Jenkins 用于除了典型的持续集成之外的其它情形——他们也将它作为管理员接口、定时任务、数据分析细流水线以及长时间运行的脚本来使用。</p>
</li>
</ul>
<h2>通用持续继承相关资源</h2>
<ul>
<li>
<p><a href="http://martinfowler.com/articles/continuousIntegration.html">持续集成是什么?</a>
是由 Martin Fowler 写的经典文章,详细讲解了 CI 背后的概念以及实现的方式。</p>
</li>
<li>
<p><a href="http://www.airpair.com/continuous-deployment/posts/continuous-deployment-for-practical-people">给务实的人准备的持续部署</a>
不是专门针对 Python 的,但是它值得一读。</p>
</li>
<li>
<p><a href="http://bitcubby.com/continuous-integration-delivery-illustrated/">持续集成和交付(插图)</a>
使用清晰的绘图说明了持续集成和交付在用于测试和数据管理时是如何工作的。</p>
</li>
<li>
<p><a href="http://www.rackspace.com/blog/diving-into-continuous-integration-as-a-newbie/">新手深入学习持续集成</a>
是一个在 Rackspace 的实习生对她是如何学习 CI 的回顾。</p>
</li>
<li>
<p><a href="http://stackshare.io/continuous-integration">StackShare 的持续集成标签</a>
列出了大量根据用户投票大致排名的托管 CI 服务。</p>
</li>
<li>
<p><a href="http://buildoutcoredev.readthedocs.org/en/latest/continous-integration.html">持续集成最佳实践</a>
包含了代码审查、合并测试以及恢复到之前版本的建议。</p>
</li>
<li>
<p><a href="http://blog.bwhaley.com/deploying-to-aws-using-ansible-docker-and-teamcity">使用 Ansible、Docker 和 Teamcity 部署到 AWS</a>
是一个例子,讲述了一种将 Teamcity CI 服务器用于自动部署的潜在方法。</p>
</li>
<li>
<p><a href="https://blog.codeship.com/continuous-integration-important/">集成测试为何重要</a>
从更高的层面说明了在一个集团中如何使用 CI 构建起开发者与开发者之间、开发者与非技术人员之间的信任。这篇文章同时也讨论了设置可靠 CI 的任务,如测试环境、<a href="/integration-testing.html">集成测试</a> 以及 CI 结果的可见性。</p>
</li>
</ul>
<h3>接下来你想为你的部署做什么工作?</h3>
<div class="row">
<div class="col-md-4">
<div class="well select-next">
<a href="/logging.html" class="btn btn-success btn-full"><svg width="28" height="30" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M1792 1344v128q0 26-19 45t-45 19h-1664q-26 0-45-19t-19-45v-128q0-26 19-45t45-19h1664q26 0 45 19t19 45zm-384-384v128q0 26-19 45t-45 19h-1280q-26 0-45-19t-19-45v-128q0-26 19-45t45-19h1280q26 0 45 19t19 45zm256-384v128q0 26-19 45t-45 19h-1536q-26 0-45-19t-19-45v-128q0-26 19-45t45-19h1536q26 0 45 19t19 45zm-384-384v128q0 26-19 45t-45 19h-1152q-26 0-45-19t-19-45v-128q0-26 19-45t45-19h1152q26 0 45 19t19 45z" fill="#fff"/></svg></a>
<p class="under-btn">我如何对应用中出现的错误进行日志记录?</p> </div>
</div>
<div class="col-md-4">
<div class="well select-next">
<a href="/web-application-security.html" class="btn btn-success btn-full"><svg width="28" height="30" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M640 768h512v-192q0-106-75-181t-181-75-181 75-75 181v192zm832 96v576q0 40-28 68t-68 28h-960q-40 0-68-28t-28-68v-576q0-40 28-68t68-28h32v-192q0-184 132-316t316-132 316 132 132 316v192h32q40 0 68 28t28 68z" fill="#fff"/></svg></a>
<p class="under-btn">我能做些什么来减少我的 web 应用安全漏洞?</p> </div>
</div>
<div class="col-md-4">
<div class="well select-next">
<a href="/docker.html" class="btn btn-success btn-full"><svg width="28" height="30" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M512 1248v192q0 40-28 68t-68 28h-320q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h320q40 0 68 28t28 68zm0-512v192q0 40-28 68t-68 28h-320q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h320q40 0 68 28t28 68zm640 512v192q0 40-28 68t-68 28h-320q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h320q40 0 68 28t28 68zm-640-1024v192q0 40-28 68t-68 28h-320q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h320q40 0 68 28t28 68zm640 512v192q0 40-28 68t-68 28h-320q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h320q40 0 68 28t28 68zm640 512v192q0 40-28 68t-68 28h-320q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h320q40 0 68 28t28 68zm-640-1024v192q0 40-28 68t-68 28h-320q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h320q40 0 68 28t28 68zm640 512v192q0 40-28 68t-68 28h-320q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h320q40 0 68 28t28 68zm0-512v192q0 40-28 68t-68 28h-320q-40 0-68-28t-28-68v-192q0-40 28-68t68-28h320q40 0 68 28t28 68z" fill="#fff"/></svg></a>
<p class="under-btn">什么是 Docker 以及如何使它适合 Python 部署?</p> </div>
</div>
</div><div id="mc_embed_signup">
<form action="//mattmakai.us2.list-manage.com/subscribe/post?u=b7e774f0c4f05dcebbfee183d&id=b22335388d" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
<div id="mc_embed_signup_scroll">
<h4>在这里注册以便每月能收到一份邮件资料,内容包含本站的主要更新、教程和 Python 书籍的打折码等。</h4>
<div class="row">
<div class="col-md-9">
<input type="email" value="" name="EMAIL" class="email form-control" id="mce-EMAIL" placeholder="邮箱地址" required>
<div style="position: absolute; left: -5000px;"><input type="text" name="b_b7e774f0c4f05dcebbfee183d_b22335388d" tabindex="-1" value=""></div>
</div>
<div class="col-md-3">
<div class="clear"><input type="submit" value="订阅" name="subscribe" id="mc-embedded-subscribe" class="btn btn-success" style="font-family: 'Helvetica Neue';"></div>
</div>
</div>
</div>
</form>
</div>
</div>
<div class="col-md-offset-1 col-md-3" id="sidebar">
<div class="panel panel-success">
<div class="panel-body">
<a href="http://www.deploypython.com/"><img src="/img/sponsored/fsp-deployment-guide.png" alt="The Full Stack Python Guide to Deployments" width="100%"></a>
<p style="font-size: .8em; margin-top: 10px;">想找到一个完整的,一步一步的部署方案吗?请看<a href="http://www.deploypython.com/">《The Full Stack Python Guide to Deployments》</a>.
</p>
</div>
</div><div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-head">邮件获取更新</h3>
</div>
<div class="panel-body">
<div id="mc_embed_signup">
<form action="//mattmakai.us2.list-manage.com/subscribe/post?u=b7e774f0c4f05dcebbfee183d&id=b22335388d" method="post" id="mc-embedded-subscribe-form" name="mc-embedded-subscribe-form" class="validate" target="_blank" novalidate>
<div id="mc_embed_signup_scroll">
<h5>注册以便每月能收到一份邮件资料,内容包含本站的主要更新和 Python 教程。</h5>
<input type="email" value="" name="EMAIL" class="email form-control" id="mce-EMAIL" placeholder="邮箱地址" required>
<div style="position: absolute; left: -5000px;"><input type="text" name="b_b7e774f0c4f05dcebbfee183d_b22335388d" tabindex="-1" value=""></div>
<input type="submit" value="订阅" name="subscribe" id="mc-embedded-subscribe" class="btn btn-success" style="font-family: 'Helvetica Neue'; margin-top: 5px;">
</div>
</form>
</div>
</div>
</div><div class="panel" id="full-toc">
<div class="panel-heading">
<h3 class="panel-head"><a href="/table-of-contents.html" style="color: #fff;">目录</a></h3>
</div>
<div class="list-group">
<a href="/introduction.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif;'>1. 简介</a><a href="/learning-programming.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>学习编程</a><a href="/why-use-python.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>为什么用 Python?</a><a href="/python-2-or-3.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Python 2 还是 3?</a><a href="/enterprise-python.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>企业 Python</a><a href="/python-community.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Python Community</a><a href="/best-python-podcasts.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Best Python Podcasts</a><a href="/best-python-resources.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>最佳 Python 资源</a><a href="/best-python-videos.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>最佳 Python 视频</a><a href="/development-environments.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif;'>2. 开发环境</a><a href="/vim.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Vim</a><a href="/emacs.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Emacs</a><a href="/python-programming-language.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif;'>3. 核心语言</a><a href="/generators.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>生成器</a><a href="/comprehensions.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>推导式</a><a href="/web-development.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif;'>4. Web 开发</a><a href="/web-frameworks.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Web 框架</a><a href="/django.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Django</a><a href="/flask.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Flask</a><a href="/bottle.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Bottle</a><a href="/pyramid.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Pyramid</a><a href="/morepath.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Morepath</a><a href="/other-web-frameworks.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>其它 Web 框架</a><a href="/web-design.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Web 设计</a><a href="/cascading-style-sheets.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>级联样式表 (CSS)</a><a href="/javascript.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>JavaScript</a><a href="/websockets.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>WebSockets</a><a href="/template-engines.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>模板引擎</a><a href="/web-application-security.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Web 应用安全</a><a href="/static-site-generator.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>静态网站生成器</a><a href="/jinja2.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Jinja2</a><a href="/data.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif;'>5. 数据</a><a href="/databases.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>关系型数据库</a><a href="/no-sql-datastore.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>NoSQL 数据存储</a><a href="/object-relational-mappers-orms.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>对象关系映射器</a><a href="/postgresql.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>PostgreSQL</a><a href="/mysql.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>MySQL</a><a href="/sqlite.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>SQLite</a><a href="/application-programming-interfaces.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif;'>6. Web APIs</a><a href="/api-integration.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>API 集成</a><a href="/api-creation.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>API 的创建</a><a href="/twilio.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Twilio</a><a href="/deployment.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif;'>7. 部署</a><a href="/servers.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>服务器</a><a href="/platform-as-a-service.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>平台即服务(PaaS)</a><a href="/operating-systems.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>操作系统</a><a href="/web-servers.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Web 服务器</a><a href="/wsgi-servers.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>WSGI 服务器</a><a href="/source-control.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>源码控制</a><a href="/application-dependencies.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>应用程序依赖</a><a href="/static-content.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>静态内容</a><a href="/task-queues.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>任务队列</a><a href="/configuration-management.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>配置管理</a><a href="/continuous-integration.html" class="list-group-item smaller-item active" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>持续集成</a><a href="/logging.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>日志</a><a href="/monitoring.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>监控</a><a href="/web-analytics.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Web 分析</a><a href="/docker.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Docker</a><a href="/caching.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>缓存</a><a href="/microservices.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>微服务</a><a href="/devops.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>DevOps</a><a href="/nginx.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Nginx</a><a href="/apache-http-server.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Apache HTTP 服务器</a><a href="/caddy.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Caddy</a><a href="/green-unicorn-gunicorn.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Green Unicorn (Gunicorn)</a><a href="/ubuntu.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Ubuntu</a><a href="/pelican.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Pelican</a><a href="/lektor.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Lektor</a><a href="/mkdocs.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>MkDocs</a><a href="/testing.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif;'>8. 测试</a><a href="/unit-testing.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>单元测试</a><a href="/integration-testing.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>集成测试</a><a href="/code-metrics.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>代码度量</a><a href="/debugging.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>调试</a><a href="/what-full-stack-means.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif;'>9. Meta</a><a href="/bots.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Bots</a><a href="/change-log.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Change Log</a><a href="/future-directions.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Future Directions</a><a href="/about-author.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>About the Author</a><a href="/sqlalchemy.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>SQLAlchemy</a><a href="/peewee.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",sans-serif; padding-left:27px'>Peewee</a> <a href="/table-of-contents.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",san-serif;background-color:#22B24C; color: #fff;'>...或者<span style="border-bottom: 1px dotted;">显示全部目录内容</span>.</a>
</div>
</div> <div class="panel">
<div class="panel-heading"><h3 class="panel-head">持续集成</h3></div>
<div class="panel-body">
重要的更新内容会通过 Twitter 账号<a href="https://twitter.com/fullstackpython">@fullstackpython</a>发布。
<hr/>
需要更加详细的教程吗?请看
<a href="http://www.deploypython.com/">《The Full Stack Python Guide to Deployments》。</a>
</div>
</div>
<div class="panel" id="mobile-toc">
<div class="panel-heading">
<h3 class="panel-head"><a href="/table-of-contents.html" style="color: #fff;">Chapters</a></h3>
</div>
<div class="list-group">
<a href="/introduction.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>1. 简介</a><a href="/development-environments.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>2. 开发环境</a><a href="/python-programming-language.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>3. 核心语言</a><a href="/web-development.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>4. Web 开发</a><a href="/data.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>5. 数据</a><a href="/application-programming-interfaces.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>6. Web APIs</a><a href="/deployment.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>7. 部署</a> <a href="/continuous-integration.html" class="list-group-item smaller-item active" style='font-family: "Helvetica Neue",sans-serif;'>» 持续集成</a>
<a href="/testing.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>8. 测试</a><a href="/what-full-stack-means.html" class="list-group-item smaller-item " style='font-family: "Helvetica Neue",sans-serif;'>9. Meta</a> <a href="/table-of-contents.html" class="list-group-item smaller-item" style='font-family: "Helvetica Neue",san-serif;background-color:#22B24C; color: #fff;'>...or <span style="border-bottom: 1px dotted;">view the full table of contents</span>.</a>
</div>
</div></div></div>
<hr/>
</div>
<div class="container">
<div class="footer pull-right">
This site is based on <a href="https://github.com/mattmakai">Matt Makai</a>'s project <a href="https://github.com/mattmakai/fullstackpython.com">Full Stack Python</a>, thanks for his excellent work!
</div>
</div>
<div class="container">
<div class="footer pull-right" style="text-align:right; font-size:85%;">
<p>此网站由 <a href="https://github.com/haiiiiiyun">@haiiiiiyun</a> 和 <a href="https://github.com/haiiiiiyun/fullstackpython.cn/graphs/contributors">开源爱好者们</a> 共同维护。
若发现错误或想贡献,请访问: <a href="https://github.com/haiiiiiyun/fullstackpython.cn/">Github fullstackpython.cn 项目</a>
</p>
</div>
</div><script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-77551377-2', 'auto');
ga('send', 'pageview');
</script><script type='text/javascript'>
var trackOutboundLink = function(url) { ga('send', 'event', 'outbound', 'click', url, {'hitCallback': function () { document.location = url; } }); }
</script>
</body>
</html>