0%

公钥经CA签名后才成为数字证书。数字证书用来保证公钥是可信任的,这是一个始自CA根证书(root certificate)的信任链。CA根证书内置CA的公钥和身份信息,CA的根证书都是自签的。CA使用其私钥签发数字证书,也就是将申请人的公钥和身份信息按X.509标准进行数字签名。比如使用浏览器浏览https站点时,就可以使用内置的CA根证书来验证服务器端的数字证书是不是有效。当然使用数字证书的领域包含但不限于web,任何需要身份鉴别的地方都可以使用数字证书。

安装

编辑文件 /etc/apt/sources.list.d/jenkins.list,其内容如下:

1
deb http://pkg.jenkins-ci.org/debian binary/

然后执行以下命令:

1
2
3
$ wget -q -O - http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key sudo apt-key add -
$ sudo apt-get update
$ sudo apt-get install jenkins

配置

端口

Jenkins默认监听8080端口,如果与其他应用程序端口冲突,修改/etc/default/jenkins文件:

HTTP_PORT=8082

然后

1
# /etc/init.d/jenkins restart

就可以了

访问控制

Jenkins默认安装是没有启用访问控制的,也就是可以随便匿名访问,要启用安全控制,访问Jenkins web界面,从”系统管理->安全设置”中配置即可。

邮件通知

打开Manage Jenkins -> Configure System:

Jenkins Location -> System Admin e-mail address 设置管理员邮箱地址
E-mail Notification -> SMTP server 输入stmp服务器地址
Default user e-mail suffix 用户邮箱后缀,比如@openwares.net
Advanced -> Use SMTP Authentication 输入smtp认证需要的User Name和password
Use SSL 如果服务器使用SSL则勾选,如果使用TLS/STARTTLS则不要勾选
SMTP Port 指定端口,默认25

如果smtp服务器使用TLS,则需要在jenkins配置文件/etc/default/jenkins中添加JAVA选项:
JAVA_ARGS=”-Dmail.smtp.starttls.enable=true” # enable STARTTLS
否则测试邮件发送会有异常:

1
2
3
4
5
6
7
8
Failed to send out e-mail

javax.mail.MessagingException: Could not connect to SMTP host: mail.openwares.net, port: 25;
nested exception is:
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
at com.sun.mail.smtp.SMTPTransport.openServer(SMTPTransport.java:1934)
at com.sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.java:638)
...

然后重新启动jenkins。

但是如果启用STARTSSL时服务器的SSL证书是自签的,又会抛出异常:

1
2
3
4
5
6
7
Failed to send out e-mail

javax.mail.MessagingException: Could not convert socket to TLS;
nested exception is:
javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sun.mail.smtp.SMTPTransport.startTLS(SMTPTransport.java:1880)
...

因为证书是不受信任的:-(。

那么还需要在jenkins配置文件/etc/default/jenkins中添加一个JAVA选项:
JAVA_ARGS=”-Dcom.sun.net.ssl.checkRevocation=false” #disable cert verify

这样就可以正常发送邮件了。

References:
[1]Jenkins Debian packages
[2]Installing Jenkins on Ubuntu

===
[erq]

账户配置

提交到gerrit的changes中的用户名和邮箱地址必须与gerrit用户信息一致,否则会被拒绝,除非有Forge XXX权限。

1
2
$ git config --global user.name "username"
$ git config --global user.email "mailbox@domain.tld"

克隆gerrit仓库
一般来说为ssh主机设置别名可以省很多事,不用每次输入复杂的远程仓库地址了:

~/.ssh/config文件中添加如下行:

1
2
3
4
5
6
Host cr
Hostname review.domain.tld
User admin
Port 29418
#如果私钥名字为id_rsa,可以省略下面一行
IdentityFile ~/.ssh/admin_rsa

然后可以这样克隆远程仓库了

1
$ git clone ssh://cr/project

而且以后都可以使用cr这个别名来代替远程gerrit仓库地址

安装commit-msg钩子

commit-msg是gerrit提供的钩子脚本,会为每个提交添加Change-Id行。

1
$ scp cr:hooks/commit-msg .git/hooks/

提交changes

首先checkout出devel分支。根据不同的策略,master有可能是禁止推送更新的。

1
2
$ git checkout devel
$ git remote update #更新远程仓库

经过一段时间的工作,有了commit后,就可以将commit提交到服务器接受代码审核。

1
$ git push origin HEAD:refs/for/devel

直接git push推送到远程devel分支是被禁止的,推送到refs/for/devel会在gerrit服务器上生成新的需要评审的changes。

可以通过增加一个远程配置来进一步简化命令行:

.git/config中添加如下行:

1
2
3
\[remote "review"\]
url = ssh://cr/project
push = HEAD:refs/for/devel

之后就可以这样推送changes了:

1
$ git push review

使用git-review

git-review是针对gerrit的一个命令

1
# apt-get install git-review

git-review默认使用gerrit远程仓库别名

1
$ git remote add gerrit ssh://cr/project

然后在工程根目录下建立git-review配置文件.gitreview

1
2
3
4
5
6
7
\[gerrit\]
host=review.domain.tld
port=29418
project=project_name
defaultbranch=devel #提交changes到devel分支,也就是推送到refs/for/devel
defaultremote=gerrit #默认即为gerrit
defaultrebase=0 #默认提交前不执行rebase操作

最后通过

1
$ git review

就可以推送changes了。

verify和code review

通过不应该通过开发人员进行verify,CI服务器会在changes提交后自动进行verify。
Code Review可以通过gerrit web接口进行。通过verify和code review的changes可以通过submit合并到目标分支。

个人分支

如果gerrit服务器提供了sandbox个人分支,那么可以将自己的阶段性工作保存在sandbox中而不用提交到gerrit服务器进行评审,直到感觉可以参加评审时再向devel分支提交changes。

1
2
3
4
5
$ git checkout devel
$ git checkout -b sandbox/yourname/foo
$ git push --set-upstream origin sandbox/yourname/foo
...
$ git push

一般来说为了devel分支的整洁,建议先在个人分支工作,等工作比较成熟后再合并回devel分支,然后再向gerrit服务器推送changes。

References:
[1]Gerrit Code Review - Uploading Changes
[2]Gerrit Code Review - Change-Ids

===
[erq]

荷兰程序员Vincent Driessen的A successful Git branching model[1]对于集中式的中小型项目是一个相当不错的分支模型。他还制作了一副pdf大图Git-branching-model

分支模型

有两个常设分支,master和devel(或叫develop,or whatever)。master分支用于最终产品发布,而devel分支用于日常开发。

其他临时性分支包括特性分支feature或叫topic分支,预发布分支release,热补丁分支hotfix。

feature用于新功能开发,分支自devel,新功能开发完毕必须merge回devel分支,或者不再需要此特性,直接丢弃分支。命名方式一般为feature-特性名或者特性编号。

release用于产品正式发布前的预发布,分支自devel。命名方式一般为release-(即将发布的版本号),比如release-1.2。release分支功能上不应该再发生变化,只是一些小的完善或者bug的修复还有实施版本策略。确认版本可以发布后,将release合并到master,并在master上打版本tag。release同时要合并回devel分支,之后可以删除release分支。

hotfix用于正式发布产品的紧急bug修复,分支自master。命名方式一般为hotfix-bug编号,比如hotfix-1312,bug编号来自bug tracking系统,比如Trac。bug修复完毕后,将hotfix分支合并回master分支,并更新产品号以及打新的tag。如果当前存在release分支,则应将hotfix合并到release分支而不是master分支。hotfix还需要合并回devel分支。之后可以将hotfix分支删除。

合并分支时使用- -no-ff选项,不让分支fast forwarding以保持完整清晰的版本历史。

个人分支

除了常设分支和临时分支外,每个开发人员还可以设立自己的个人分支(personal branch)。个人分支以自己的名字命名,分支自devel。个人分支方便开发人员保存和在不同机器间同步未最终完成的工作成果,代码重构,并且可以减少devel分支的commit,保持devel分支的整洁。个人分支上的工作告一段落后,更新本地代码库,将个人分支上的工作成果合并到devel分支,然后推送devel分支到中央仓库。

代码审核

master分支只有项目管理员可以touch,其他开发人员无法向master推送更新。而开发人员向devel分支推送的更新必须经过gerrit代码审核服务器,在通过其他开发人员的code review和CI服务器的自动verify后,才可以正式merge到devel分支。

其他临时分支和个人分支不经过gerrit,直接进入中央仓库。

持续集成

每当开发人员向devel推送更新,这在gerrit叫做change,CI服务器会自动对新提交的change进行编译和运行单元测试,根据结果给于适当的verify值。

当代码通过审核merge到devel后,自动触发CI服务器,拉取devel分支,然后编译部署到测试环境进行自动化测试和人工测试。

而master分支发布产品时也可以通过触发CI进行自动编译和部署到产品环境。

References:
[1]A successful Git branching model
[2]Git分支管理策略
[3]实用 Git 工作流
[4]一个成功的Git分支模型

===
[erq]

gerrit从2.6开始,默认不再添加verified category,也就是changes上就看不到verified label了。

具体的原因见gerrit的Change 44084。这是为了简化out of the box工作流,如果需要与jenkins等CI环境集成,则需要手动添加verified category,只要在All-Projects的project.config文件里添加5行文本就可以了。

添加V标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ mkdir temp && cd temp
$ git clone ssh://cr/All-Projects.git

Cloning into 'All-Projects'...
remote: Counting objects: 22, done
remote: Finding sources: 100% (22/22)
remote: Total 22 (delta 1), reused 6 (delta 1)
Receiving objects: 100% (22/22), 5.33 KiB 0 bytes/s, done.
Resolving deltas: 100% (1/1), done.
Checking connectivity... done.
Note: checking out 'a30b5de24cdd7993bbe3398e57b1cb771cbb1fc2'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

git checkout -b new_branch_name

$ cd All-Projects
$ vim project.config

在文件project.config中添加如下5行:

1
2
3
4
5
\[label "Verified"\]
function = MaxWithBlock
value = -1 Fails
value = 0 No score
value = +1 Verified

然后提交到远程仓库

1
2
3
4
5
6
7
8
9
10
11
12
$ git commit -a -m "add verified category"
$ git push origin HEAD:refs/meta/config

Counting objects: 15, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 323 bytes 0 bytes/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1)
remote: Processing changes: refs: 1, done
To ssh://cr/All-Projects.git
93dc4d8..22b46f7 HEAD -> refs/meta/config

因为在分离头(detached HEAD)状态,所以手工指定将当前HEAD push到远程引用refs/meta/config。

登录gerrit站点,changes上面就有V标签了。

verified label的用法见官方文档。

References:
[1]HOW TO EDIT THE PROJECT.CONFIG FOR ALL PROJECTS IN GERRIT

===
[erq]

Lambda表达式本质就是一个匿名函数,其理论基础来自于λ演算。不过Lambda表达式是受到很多限制的匿名函数,比如有些语言只允许有一条表达式。闭包是持有自由变量从而具有状态的函数,闭包通常使用匿名函数来实现。闭包拥有的自由变量类似于对象拥有的成员变量。

OpenID是Authentication,OAuth是Authorization。OpenID只是认证,而OAuth包含了认证和授权。