最近一个高性能API项目中需要针对DEV,STG,PRO三个环境实现定制化部署。
背景:这三个环境的依赖,file path等存在各自的差异,CI,CD的时候需要按照不同的环境定制话不同的部署(主要是不同的环境,项目的配置文件不同)。
其实这个是违背CI,CD的产品包与配置文件相独立这个原则的。
HowTo
链接:http://maven.apache.org/plugins/maven-assembly-plugin/
assembly插件与pom文件结合使用
1, 配置profile
<profiles>
<profile>
<id>dev</id>
<properties>
<app.env>dev</app.env>
<confDir>src/main/conf/env/local</confDir>
<testTargets>com/..../itemapi/*Test*.java</testTargets>
</properties>
</profile>
<profile>
<id>stg</id>
<properties>
<app.env>stg</app.env>
<confDir>src/main/conf/env/local</confDir>
<testTargets>com/..../itemapi/*Test*.java</testTargets>
</properties>
</profile>
<profile>
<id>pro</id>
<properties>
<app.env>pro</app.env>
<confDir>src/main/conf/env/local</confDir>
<testTargets>com/..../itemapi/*Test*.java</testTargets>
</properties>
</profile>
</profiles>
以上的配置是根据maven命令行参数 -p来设置app.env, confDir的变量值。比如:-p stg
2, 配置assemly插件
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<tarLongFileMode>posix</tarLongFileMode>
</configuration>
</plugin>
这里只是简单地将assemly插件的具体配置文件设为assembly.xml
3, assembly.xml文件配置
<?xml version="1.0" encoding="UTF-8"?>
<assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>runtime-dist</id>
<formats>
<!-- 指定打tar.gz包 -->
<format>tar.gz</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<!-- 将项目所依赖的所有runtime范围的jar包copy到部署根目录下的lib文件夹下,且个个jar文件的权限为644 -->
<dependencySet>
<unpack>false</unpack>
<scope>runtime</scope>
<outputDirectory>lib</outputDirectory>
<fileMode>0644</fileMode>
</dependencySet>
</dependencySets>
<files>
<file>
<!-- 将文件 src/main/bin/env/${app.env}/env.sh 拷贝到部署根目录下的bin/env.sh,且文件权限为0644 -->
<source>src/main/bin/env/${app.env}/env.sh</source>
<destName>env.sh</destName>
<outputDirectory>bin</outputDirectory>
<!-- filtered属性设置为true,可以将sh文件中的的变量替换为pom文件中的变量值 -->
<filtered>true</filtered>
<fileMode>0644</fileMode>
<lineEnding>unix</lineEnding>
</file>
</files>
<fileSets>
<fileSet>
<!-- 除 src/main/bin/env/文件夹之外,将整个 src/main/bin/ 拷贝到部署根目录下的bin/env.sh,
且文件权限均为0744 -->
<directory>src/main/bin</directory>
<outputDirectory>bin</outputDirectory>
<fileMode>0744</fileMode>
<filtered>true</filtered>
<excludes>
<exclude>env/</exclude>
</excludes>
</fileSet>
<fileSet>
<directory>src/main/conf/env/${app.env}</directory>
<outputDirectory>conf</outputDirectory>
<fileMode>0644</fileMode>
<filtered>false</filtered>
</fileSet>
<fileSet>
<directory>src/main/conf/common</directory>
<outputDirectory>conf</outputDirectory>
<fileMode>0644</fileMode>
<filtered>false</filtered>
</fileSet>
</fileSets>
</assembly>
4, 脚本文件中的变量替换
export JAVA_BIN="/usr/bin/java"
export JAVA_OPTION="-Xmx2048m -Xms512m -Duser.timezone=UTC -Dspring.profiles.active=${app.env} -Djava.security.egd=/dev/urandom"
因为我们将filtered属性设置为了true
在实际打包部署过程中assembly插件会将bash脚本中的变量 ${app.env}的值替换为pom中定义的值。
5, jenkins的配置
-U
clean
assembly:assembly
-DargLine=''
-P $ENV_PROFILE
-Dapp.env=$ENV_PROFILE
-Dspring.config.location=src/main/conf/env/local/application.properties
jenkins指定profile(-P $ENV_PROFILE)就可以按照发布环境做定制化发布了。
这样也有弊端,就是在STG环境测试完之后,不能将测试完的STG包直接发布到PRO。
PRO还需要重新编译打包然后再发布,这样可能会带来潜在的风险。
理想情况是包就是产品且独立于环境,包可以在任何环境部署。发布到PRO的包就是STG充分测试过的包。
这个留待后续改进!