编译工具

代码开发完毕后,我们需要将其编译为可运行的代码。编译工具与源代码使用语言有密切关系,常用的编译工具有:

  • Java 常使用Maven, Ant 或 Gradle
  • C或C++ 常使用make或各种make的衍生品。
  • iOS开发使用xcode
  • PHP、Python等脚本语言常无需编译,一般可将代码打包到一个单一文件,故编译可以使用zip压缩工具代替。

编译实践规范

编译工具是从源代码到目标程序的最重要一环。在实际工作过程中,常因为编译环境的不同,使得目标程序出现差异。因此有必要在团队内建立统一的编译规范:

  • 统一编译工具。对开发者机器、测试环境和生产环境的编译器进行统一,包括编译器版本及配置
  • 统一第三方库。第三方库的升级可能带来接口变更,导致程序发生不可预期的计算错误或崩溃。因此,建议显示地指定依赖的第三方库的版本号。
  • 便捷的编译操作。当一个新的开发者签出代码后,应该根据编译指引文档,经过一两个操作就能编译目标代码。避免在编译过程中,需要开发者自行解决一些依赖或配置错误。
  • 显示指明编译器的版本。不同的编译工具可能编译出来不同的内容,比如JDK7和JDK8,c++98和gnu++。

Jenkins

Jenkins是一个可扩展的开源编译工具。通过对插件、编译工作节点的设置,可以完成对所有开发语言的编译工作。同时,它更是一个强大的自动化集成、部署的工具,下一个章节我们即将介绍。

通过命令行安装Jenkins

以CentOS 7为例通过包管理工具进行安装,其他的版本可以参考jenkins官方安装文档:https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkins

> sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo

> sudo rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key

> sudo yum install -y java

> sudo yum install -y jenkins

> sudo yum install -y git subversion #安装必要的版本管理工具

服务启动后通过 http://127.0.0.1:8080/ 即可访问 Jenkins。根据提示,sudo cat /var/lib/jenkins/secrets/initialAdminPassword 获得登录密码,然后选择需要的组件,完成系统初始化安装。

通过Docker安装Jenkins

docker run -p 8080:8080 -p 50000:50000 -v jenkins_home:/var/jenkins_home jenkins

安装完毕后,通过 http://127.0.0.1:8080/ 即可访问 Jenkins

安装Jenkins组件

根据需要,我们可以安装组件,来扩充Jenkins的功能,从而满足项目的编译或自动化部署需求。常用组件的功能介绍如下:

插件名称 介绍
Folders Plugin 在Jenkins中建立目录
OWASP Markup Formatter Plugin 允许用户在描述信息中编写安全的HTML文本。
build timeout plugin 自动设置编译超时
Timestamper 在输出中,增加时间戳
Ant Plugin 支持使用Apache Ant编译项目
Maven Project Plugin 支持使用Maven编译项目。其他的编译工具还包括:CMake Plugin,
Xcode integration 通过Jenkins调用xcode指令,完成编译和打包过程
Gradle Plugin Gradle项目编译支持。 Android开发必备。
Pipeline Jenkins官方支持的自动化套件。用于将自动化发布的过程、流程管理
Pipeline: Stage View Plugin Pipeline 视图。可更好的对Pipeline任务进行展示。
GitHub Plugin 集成Github访问
Git Plugin 支持通过GIT版本管理系统获取代码。Jenkins支持所有常用的版本管理工具,如Subversion Plug-in ,CVS Plug-in, Mercurial plugin
SSH Slaves plugin 允许通过SSH建立Jenkins子节点。
Matrix Authorization Strategy Plugin 权限管理插件。支持按照用户/用户组,项目管理权限。其他的授权管理还包括基于角色授权的Role-based Authorization Strategy
PAM Authentication plugin linux可插入认证模块通过Linux系统的用户、密码管理Jenkins登录。其他的用户登录方式还包括LDAP Plugin,GitLab Authentication Plugin 联合授权,OpenID pluginGitHub Authentication plugin
Email Extension Plugin 更高级的Email设置。支持邮件自动触发,内容模板等
Lockable Resources plugin 锁插件。可建立锁,防止并发冲突。如可防止系统同时运行部署可用。当发生锁冲突时,后一个工作将等待锁结束后才运行。
Copy Artifact Plugin 允许项目之间进行编译结果复制
Build Pipeline Plugin 显示编译的上下游依赖
Environment Injector Plugin 在项目设置中,注入环境变量

同时推荐一些暂时还有没添加到 jenkins插件列表的插件。pubu 零信, 用于构建通知。

建立编译子节点

Jenkins使用节点来运行编译任务。默认的,系统将在Jenkins系统本机建立一个master节点,用于任务编译。但为了保证编译环境的稳定,我们推荐建立专用服务器,针对每一种编译环境分配独立的主机或虚拟机。推荐使用Vagrant进行虚拟机管理。

准备材料

  1. 已经准备好的Jenkins系统
  2. 一台新的机器,作为编译专属机器。该机器与Jenkins在同一个局域网内,如IP均为:192.168.1.X。
  3. 系统可采用CentOS或Ubuntu
  4. 安装VirtualBox。
  5. 安装Vagrant

建立Jenkins私钥

Jenkins与节点之间将使用SSH进行通讯,在建立节点之前,先在Jenkins系统中生成授权公私钥文件

# cd ~; mkdir -p jenkins/.ssh; cd jenkins/.ssh #准备.ssh目录

# ssh-keygen -t rsa -b 4096 -C "[email protected]" -f id_rsa #建立公私钥文件,提示Passphrase时不设置,直接敲回车。

# cp id_rsa.pub ~/ #复制公钥文件,以后备用。

# chmod 0700 .; chmod 0600 id_rsa*; #修改私钥文件夹及文件权限,禁止其他用户读取

# cd ../; sudo mv .ssh /var/lib/jenkins/ #将公私钥复制到Jenkins用户的家目录

# sudo chown -R jenkins:jenkins /var/lib/jenkins/.ssh #变更私钥文件夹及文件所有者为Jenkins运行用户

建立Jenkins私钥凭证

接下来,使用Jeknins私钥,建立授权凭证。

使用管理员账户,登录到jenkins,依次进入 Credentials =》 Jenkins Credentials Provider (global) =》 Add Credentials,进入授权新增页。

  1. 授权分类[Kinds]中选择 SSH Username with private key
  2. 授权作用域[Scope]保持默认,Global。
  3. 登录用户名[Username]填入上一步我们建立的用户名, jenkins
  4. 密钥[Private Key]选择 从Jenkins主机的~/.ssh目录中读取 [From the Jenkins master ~/.ssh]。系统将自动找到我们刚建立的id_dsa文件作为私钥
  5. 密码[Passphrase]留空
  6. ID填入 jenkins_master_key, 在以后我们写命令行的时候会使用到
  7. Description留空
  8. 点击OK, 保存本授权信息

后续即可在需要授权时,需选择此项,将显示为『jenkins』。

建立编译节点文件

mkdir /data/vm && cd /data/vm vi Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :`
VM = "virtualbox"
Vagrant.configure(2) do |config|
  config.vm.define :jdk8 do |jdk8|
    jdk8.vm.box = "centos/7"
    jdk8.vm.hostname = "jdk8"
    jdk8 "public_network", ip: “192.168.1.10"
    jdk8.vm.provider VM do |v|
      v.memory = 512
    end
  end
end

vagrant up jdk8 --provision

上述指令声明并启动了一个名为jdk8的虚拟机,其使用centos7系统,IP为

192.168.1.10。注意IP需要设置为与当前机器统一局域网的网段的IP,否则将导致无法连接。

安装编译环境

接下来,登录到jdk8虚拟机上,安装编译环境,包括maven,oracle jdk8等。

$ vagrant ssh jdk8
# sudo yum -y install wget git
# sudo yum -y install maven
# wget --no-cookies --no-check-certificate --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u121-b13/e9e7ea248e2c4826b92b3f075a80e441/jdk-8u121-linux-x64.tar.gz"
# sudo mkdir -p /opt/ && cd /opt/
# sudo tar xzf ~/jdk-8u121-linux-x64.tar.gz
# sudo alternatives --install /usr/bin/java java /opt/jdk1.8.0_121/bin/java 2
# sudo alternatives --set java /opt/jdk1.8.0_121/bin/java
# sudo alternatives --install /usr/bin/jar jar /opt/jdk1.8.0_121/bin/jar 2
# sudo alternatives --install /usr/bin/javac javac /opt/jdk1.8.0_121/bin/javac 2
# sudo alternatives --set jar /opt/jdk1.8.0_121/bin/jar
# sudo alternatives --set javac /opt/jdk1.8.0_121/bin/javac
# java -version
java version "1.8.0_121"
Java(TM) SE Runtime Environment (build 1.8.0_121-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
# docker run -t -i airdock/oracle-jdk:jdk-8u112 java -version

修改maven配置,将maven仓库配置为国内地址,或者自己的私有仓库。

<mirror>
  <id>alimaven</id>
  <name>aliyun maven</name>
  <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
  <mirrorOf>central</mirrorOf>
</mirror>

编译用户及关联授权

在jdk8系统中,新建用户,并允许jenkins系统进行登录。

# vagrant ssh jdk8    #登录到jdk8。
# sudo useradd jenkins  #创建用户
# sudo su jenkins -
# cd ~
# mkdir -p ~/.ssh && chmod 0744 ~/.ssh/  #建立密钥目录及可登录授权文件
# touch ~/.ssh/authorized_keys && chmod 0600 ~/.ssh/authorized\_keys   #设置auth keys权限。必须为0600
# echo "ssh-rsa ... [email protected]" >> ~/.ssh/authorized\_keys  #将上一步在Jenkins机器上生成的公约文件内容,放入authorized_keys内。

关联节点

通过Jenkins WEB菜单,进入 系统管理 =》 管理节点 =》 新建节点, 进入节点新建指引流程

  1. 节点名称填 JDK8-192.168.1.10
  2. 节点类型选择:Permanent Agent(永久节点), 进入下一步
  3. "# of executors”为可并发运行的数量,由于Java项目间可能存在依赖编译或子项目编译,节点设置太少可能导致资源死锁。 推荐填4或2.
  4. 远程目录填 /home/jenkins ,即编译节点的登录用户家目录。
  5. 标签填JDK8
  6. 用法:尽可能的使用此节点
  7. 启动方法:Launch slave agent via SSH。 (依赖插件: SSH Slaves plugin)
  8. 主机[Host]: 192.168.1.10 , 填写jdk8的IP地址
  9. Credentials 选择”jenkins”
  10. Availability: "Keep this agent online as much as possible”, 保持默认值,即保持节点一直可用。
  11. 点击Save,完成。
  12. 保存后,节点将自动进行连接。 如发生错误,可点击左侧日志查看连接失败信息并修复
  13. 连接成功后的节点页面如下图:

编译节点 更多编译节点的安装,如JDK7, 脚本语言编译,Gradle等可通过自动化部署脚本实现,在第N章,我们将进行详细介绍。

建立编译任务

我们以一个简单的Java项目为例,建立第一个编译项目,将源代码编译成需要的目标文件。 在第3章源代码管理中,我们已经搭建了gitlab服务器,用于存储我们的源代码,Jenkins可以从gitlab中获得代码,通过节点进行编译得到目标文件。 我们在gitlab中建立一个新的项目,登录gitlab,新建项目,从URL导入项目, URL填写一个简单的JAVA工程地址: https://github.com/gikoluo/DevOps_JavaProject_Sample 。完成后,我们得到了在私有仓库中的项目地址: http://10.100.18.106/sample/java-sample

创建gitlab部署私钥 进入Gitlab管理界面,点击右上角设置下拉菜单,找到 Deploy Keys并进入。 点击 New Deploy Key,将Jenkins服务器的公钥复制到Key输入框,命名为『Jenkins Deploy Key』 再进入java-sample项目,找到项目的 Deploy Keys , Enable 刚才加入的Deploy Key。

创建Jenkins编译任务 [需要安装 Maven Integration plugin ] 进入jenkins web页面,点击创建 先建立一个目录,项目名称填 sample, 下方选择目录[Folder],保存。 在目录下,再点击创建新任务,任务名称填: java-sample, 下方选择构建一个Maven项目, 保存。 在任务编译页面中,设置属性,重要属性包括:

  • 源码管理,选择git,填入测试项目的的gitlab地址。git@gitlab:sample/java-sample.git,
  • 授权选择jenkins 项目完成打包后,将生成一些jar文件。设置部署包文件,将包提出出来,以便下载和后续使用。在

设置编译工具, JDK8, 设置 Maven Home

放入Jenkins和JDK8节点。

$ cat ~/.ssh/config
Host gitlab
  User git
  Hostname 172.17.0.1
  Port 7022
  IdentityFile ~/.ssh/id_rsa

建立maven 填写git地址,选择私钥 设置部署包文件 运行,检查编译过程和编译结果。

如果一切正常,我们将在任务页面中看到编辑并存档的jar包。下载之后,本地测试运行一下: java -jar multi1-6.12-SNAPSHOT.jar

编译工作就已经全部完成了。对目标文件的配置及发布管理我们在下一章介绍。

建立Sonar服务

Sonar能对代码进行静态检查,分析编码规范、代码重复率等,并估算代码债务时间。对于代码走查,帮助开发人员进行代码重构提供重要的参考。

建立Sonar服务器 Sonar服务我们使用docker进行安装:

docker run -d --name sonarqube-mysql \
  -e MYSQL_ROOT_PASSWORD=sonar \
  -e MYSQL_DATABASE=sonar -e MYSQL_USER=sonar \
  -e MYSQL_PASSWORD=sonar \
  -v /opt/docker/sonarqube/mysql:/var/lib/mysql mysql:latest

docker run -d --name sonar \
  --link sonarqube-mysql:mysql \
  -p 9000:9000 -p 9092:9092 \
  -e SONARQUBE_JDBC_USERNAME=sonar \
  -e SONARQUBE_JDBC_PASSWORD=sonar \
  -e SONARQUBE_JDBC_URL="jdbc:mysql://mysql:3306/sonar?useUnicode=true&characterEncoding=utf8&rewriteBatchedStatements=true" \
  -v /data/docker/sonarqube/conf:/opt/sonarqube/conf \
  -v /data/docker/sonarqube/data:/opt/sonarqube/data \
  -v /data/docker/sonarqube/extensions:/opt/sonarqube/extensions \
  -v /data/docker/sonarqube/logs:/opt/sonarqube/logs \
  sonarqube

安装Jenkins插件

  1. 在Jenkins插件中心找到 SonarQube, 安装。
  2. 在Jenkins中,进入 管理Jenkins > 系统设置, 找到SonarQube配置。
  3. 勾选 Enable injection of SonarQube server configuration as build environment variables
  4. 填入正确的Sonar地址。

安装Sonar节点 我们公用jdk8,安装sonar。 使用Ansible代码 在Jenkins节点中,增加sonar tag 配置SonarQube扫描器

  • 进入Jenkins,管理 > 全局工具管理
  • 增加SonarQube扫描器,名字: Sonar,SONAR_RUNNER_HOME 填 /opt/sonar-scanner

配置任务

  • 进入Jenkins,找到编译一个编译任务,进入修改页面
  • 在编译后操作中,增加 Build Sonar。
  • 填入Sonar参数,保存
  • 重新编译任务,编译完成后,将在任务页面,出现sonaar标志及连接。点击后即可查看sonar代码扫描结果。
  • 注:对Maven项目进行在编译后执行sonar官方已不再建议使用。我们将在下一张介绍如何在Pipeline流程中使用sonar。

results matching ""

    No results matching ""