自动化部署的一次实践

问题

现有的状态:需要部署最新代码时,手动在Bamboo上trigger build,然后手动到nexus目录下下载tar包,然后手动用Filezila上传到Server对应目录下,解压后运行。

期望达成的状态:需要部署最新代码时,直接在Server上跑一个脚本,然后它会自动下载并解压。

分析

对于存在的问题,将其细化拆分,一一分析解决方案。

问题1:需要每次手动trigger build。
解决1:在Bamboo上设置自动化的build schedule。

问题2:需要手动下载并解压build好的tar包。
解决2:写一个download package的脚本。

至此,上述的问题已经得到解决。

解决

Fix 1: Configure build schedule -> Bamboo

Bamboo -> Action/Configure Branch -> Plan Configuration -> Triggers -> Add trigger

Bamboo上的trigger build strategy(笔者认为)可以分为两大类:一是poll build,去poll repo,有change的话就build。二是fix build,受到trigger后一定会做一个build,不管有没有change。
而这两大类有有各种细分:比如按频率来算,每小时一次。比如按时间来算,早晚8点一次。比如设置一个规则,满足条件的话trigger。具体的可以看这里:Triggering builds - Bamboo Support

bamboo-build

总的来说,Bamboo的设置还是比较容易上手的。

Fix 2: Add download script -> shell

shell script可以分为三个部分,第一部分,读取输入参数。这里主要用到了getopts这个命令。

## get input params
while getopts hxp:b: arg; do
case $arg in
    h)
    echo "downloadsnap [-x (extract after download)] [-p <package-name>] [-b <branch>]"
    exit
    ;;
    p)
    package=$OPTARG
    ;;
    x)
    extract=1
    ;;
    b)
    branch=/$OPTARG
    ;;
esac
done

第二部分,实现核心逻辑,即下载。这里主要用到了wget命令。

## search on nexus and download latest snapshots
mkdir snaptemp
rm ./download_info.txt 2> /dev/null
date +%x_%H:%M:%S:%N >>download_info.txt
pkglst=$(wget -r -A package.tarxxx -P snaptemp --no-parent http://path/to/repo/${branch}/path/to/project/ \
    |& grep some_key_word | awk '{print $NF}' | sort -V | awk -F '/' '{ map[$(NF-2)]=$0;} END{for( key in map) print map[key];}' | grep -i "$package")
echo "$pkglst" | while read line; do
    echo $line
    wget -r -A package.tar -P snaptemp --no-parent $line 
done

第三部分,后续一些清理工作。这里主要是清理文件(mv,rm),解压缩(tar)。

## move from temp folder to base folder and extract
for f in $(find snaptemp -name \*package.tar); do
    rm ./$(basename $f) &>/dev/null||:
    mv $f $(basename $f)
    if [[ $extract -eq 1 ]]
    then
        tar xvf $(basename $f)
        rm ./$(basename $f) &>/dev/null||:
    fi
done
rm -rf ./snaptemp

注:一些具体的路径名和其它细节已经隐去,不过大体实现的思路和逻辑都描述出来了。写任何的script,大都可以分为以上三块:读取输入,处理,清理环境。

优化

在实现的过程中,又发现一个问题,即所有build好的snapshot文件上传的路径都是一样的。如下在pom.xml中的定义:

<distributionManagement>
    <repository>
        <id>my-releases</id>
        <name>My Releases</name>
        <url>http://path/to/my/releases</url>
    </repository>
    <snapshotRepository>
        <id>my-snapshots</id>
        <name>My Snapshots</name>
        <url>http://path/to/my/snapshots</url>
    </snapshotRepository>
</distributionManagement>

当大家都用的是一个git branch的时候,完全没有问题,但是如果有多个branch同时开发并需要联动Bamboo自动化部署时,就有问题了。

这里的问题是:难以快速区分不同branch代码的build版本。举例,开发A用branch_a build出来的一个包是repo_1.5.5,开发B用branch_b build出来的一个包是repo_1.5.6,两者在同一目录下。
虽然两者的version不一样,但是很难快速区分,需要分别去看自己的build log,然后根据里面打出的version版本来做出判断。但是,以上的自动化方案没有办法做出这种判断。

解决的方案有很多,列举两个:

  • 1.在build好的包中加入一些metadata信息,包含git branch,download script读取metadata,只抓去对应的branch的包。
  • 2.根据路径区分不同branch,比如branch_a的包会上传到/branch_a/repo,以此类推。download script就只需要到对应的路径下抓取。

方案一的pom部分改动如下,主要是用了buildnumber-maven-plugin和maven-jar-plugin,前者生成一些git info,后者将这些信息写入jar。

<!-- generate build timestamp, version, branch related info -->
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>buildnumber-maven-plugin</artifactId>
    <version>1.4</version>
    <executions>
        <execution>
            <id>generate-timestamp</id>
            <phase>validate</phase>
            <goals>
                <goal>create</goal>
            </goals>
            <configuration>
                <format>{0,date,MMM-dd HH:mm:ss z}</format>
                <items>
                    <item>timestamp</item>
                </items>
                <buildNumberPropertyName>buildDateTime</buildNumberPropertyName>
                <getRevisionOnlyOnce>true</getRevisionOnlyOnce>
            </configuration>
        </execution>
        <execution>
            <id>generate-buildnumber</id>
            <phase>validate</phase>
            <goals>
                <goal>create</goal>
            </goals>
            <configuration>
                <revisionOnScmFailure>0</revisionOnScmFailure>
                <useLastCommittedRevision>true</useLastCommittedRevision>
                <buildNumberPropertyName>buildRevision</buildNumberPropertyName>
                <scmBranchPropertyName>buildBranch</scmBranchPropertyName>
            </configuration>
        </execution>
        <execution>
            <id>create-metadata</id>
            <phase>generate-resources</phase>
            <goals>
                <goal>create-metadata</goal>
            </goals>
            <configuration>
                <attach>true</attach>
                <properties>
                    <buildBranch>${buildBranch}</buildBranch>
                </properties>
                <addOutputDirectoryToResources>true</addOutputDirectoryToResources>
            </configuration>
        </execution>
    </executions>
</plugin>

<!-- add git branch info to metadata when building jar -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>3.1.1</version>
    <configuration>
        <archive>
            <index>true</index>
            <manifestEntries>
                <Git-Revision>${buildRevision}</Git-Revision>
                <Build-Time>${buildDateTime}</Build-Time>
                <Git-Branch>${buildBranch}</Git-Branch>
            </manifestEntries>
        </archive>
    </configuration>
</plugin>

方案二的pom部分改动如下:主要是用了maven-deploy-plugin来override snapshot location。

<!-- set up overridden snapshot deploy location -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-deploy-plugin</artifactId>
    <version>3.0.0-M1</version>
    <configuration>
        <altSnapshotDeploymentRepository>
            my-snapshots::some/path${buildBranch}
        </altSnapshotDeploymentRepository>
    </configuration>
</plugin>

总结

针对开发中的问题,本文从三个层次实现了自动化部署,提高了开发测试的效率。

  • Configure build schedule -> Bamboo
  • Add download script -> shell
  • Change snapshot deploy location -> pom.xml

猜你喜欢

转载自www.cnblogs.com/maxstack/p/10654128.html