CI / CD流程更新:准备和计划

图片

在2020年,可能很难在没有以下单词之一的堆栈描述中找到项目:IaC,微服务,kubernetes,docker,aws / azure / gcloud,区块链,ML,VR等。太好了!进步不会停滞不前。我们正在成长,我们的项目也在成长,出现了解决现代问题的更加便捷和实用的工具。

你好。所以我想开始这篇文章。但是后来我回顾了一些事情,与同事交谈,意识到我会错。仍然有超过15年的项目,管理者和参与者都是老信徒,因此这些项目具有古老的技术堆栈,很难在现有动物园中维护。由于某种原因,该项目无法进行全局更新(客户是starover,没有更新,项目很大,迁移被延迟,或者每个人都满意),因此您必须予以支持。当仍在积极开发类似项目时,情况更令人不快。就像雪球一样。客户和公众需要功能,代码需要交付,服务器需要关注和维护...但是位包-因此,总的来说,不再支持汞建议仅考虑这种情况。

将考虑什么:转换mercurial-git,将CI从CruiseControl.NET迁移到TeamCity,从git-deployment迁移到Octopus ,并对整个过程进行少量描述。

文本的内容很多,因此将其分成多个部分以方便理解。将有一个目录。
第1部分:是什么,为什么不喜欢,计划,要花点时间。我将这部分称为技术性的。
第2部分:团队合作精神。
第3部分:章鱼部署。
第四部分:幕后花絮。不愉快的时刻,未来的计划,可能是常见问题解答。最有可能的是,它也可以称为近技术。

由于许多原因,我不会将其称为重复指南:由于时间紧缺而无法完全沉浸在项目流程中,对此类事物的实践不足,巨大的整体作品将所有子项目紧密地交织在一起,以及许多其他细微差别,这些细微之处使您不知所措,忍受不了,但无论如何都不要取悦。而且,由于项目的功能(这是非常独特的),某些步骤将专门针对这种情况而定制。

经典介绍


我们有一个Mercurial资源库,300多个(开放!)Brunches,ccnet,另一个ccnet + git(用于部署),以及带有我们自己的配置和单个客户端的一整套项目模块,四个环境以及IIS中的一整套池以及cmd脚本,SQL,五百多个域,两打构建以及活跃的开发。并非所有这些都是必要的,但它确实有效,并且很不方便且很长。唯一令我担忧的是存在其他需要我注意的项目。没有如此集中的工作和干扰,在处理如此庞大的任务的过程中,没有什么比这更危险了。

我知道早晚我将不得不注意其他任务,这就是为什么我花大量时间研究现有基础架构,以便至少以后不会出现未解决的问题的原因。

遗憾的是,由于NDA的原因,我无法完整描述该项目,因此将考虑一般技术要点。与项目相关的所有名称也将被涂上。对于屏幕截图上的黑色涂片,我深表歉意。

该项目的主要特点之一是,它具有许多具有一个核心但模块配置不同的模块。还有一些采用“特殊”方法的模块,这些模块是为经销商和特别是大型客户设计的。一个模块可以为多个客户提供服务。客户应被理解为获得特定模块访问权限的独立组织或一群人。每个客户端都可以访问自己的域,具有自己的设计和自己独特的默认设置。客户端由其使用的域标识。

该项目这部分的总体方案可以表示如下:


如您所见,核心在所有地方都使用相同,并且可以使用。

出现任务以审查和更新CI / CD流程的原因:

  1. CruiseControl.NET被用作构建系统。原则上和他一起工作是一种可疑的乐趣。多个屏幕上的XML配置,一堆依赖项以及彼此之间的链接配置,缺乏针对现代问题的现代解决方案。
  2. 项目中的某些开发人员(主要是潜在客户)必须有权访问构建服务器,他们有时喜欢更改ccnet配置,但不应更改。猜猜接下来会发生什么。您需要在CI系统中具有简单方便的权限管理,而又不影响开发人员对服务器的访问。简而言之,没有文本配置-没有地方可以用顽皮的手攀爬。
  3. - … CCNET, git. (. ).
  4. , . , . 
  5. - , — ( ) .
  6. . ? ? ? .
  7. 资源使用不足,构建和交付代码的过程过时。

图至第3段:


在计划阶段,决定使用Teamcity作为构建系统,并使用Octopus作为部署系统。客户的“铁”基础架构保持不变:用于开发,测试,登台和生产的单独的专用服务器,以及代理商服务器(主要是生产环境)。

向客户提供了其中一个模块示例的概念证明,编写了一项行动计划,并进行了准备工作(安装,配置等)。描述这一点可能没有任何意义。如何安装团队城市可以在官方网站上阅读。我将分别讨论新系统的一些规定要求:

  1. 易于维护,并承担所有后果(备份,更新,解决问题,如果有的话)。
  2. 普遍性。理想情况下,开发一个通用方案,根据该方案组装和交付所有模块,并将其用作模板。
  3. 减少添加新的构建配置和维护的时间。客户端被添加/删除。有时有必要进行新的设置。创建新模块时,必须不延迟其交付配置。

大约在这一点上,我们想起了使用位桶停止对Mercury存储库的支持,并且添加了将存储库转移到git的同时保留分支和提交历史的要求。

准备:存储库转换


似乎有人清楚地解决了这个问题,摆在我们面前而不是我们。您只需要找到一个现成的工作解决方案。事实证明,快速导出并不是那么快。另外,它没有用。不幸的是,没有日志和屏幕截图了。事实是他做不到。Bitbucket不提供自己的转换器(但可以提供)。还有更多的谷歌方法,也可以。我决定编写自己的脚本,无论如何这不是唯一的软件资源库,它将在将来派上用场。此处将介绍早期的发展(因为它们仍然保持相同的形式)。工作的逻辑看起来像这样:

  1. 我们以扩展汞柱为基础。 
  2. 我们获得了汞库所有分支的列表。 
  3. 我们转换分支的名称(感谢Mercurial和开发人员提供的分支名称中的空格,特别感谢为您带来欢乐的变音符号和其他字符)。
  4. 制作书签(hg书签)并推入中间存储库。做什么的?因为是bitbucket,而且因为您无法创建与分支名称相同的书签(例如,暂存)。 
  5. 在新的(已经是git)存储库中,从分支名称中删除后缀,并将hgignore迁移到gitignore。 
  6. 推送到主存储库。

根据要点列出命令:

  1. $ cd /path/to/hg/repo
    $ cat << EOF >> ./.hg/hgrc
    [extensions]
    hggit=
    EOF
    
  2. $ hg branches > ../branches
    
  3. #!/usr/bin/env bash
    hgBranchList="./branches"
    sed -i 's/:.*//g' ${hgBranchList}
    symbolsToDelete=$(awk '{print $NF}' FS=" " ${hgBranchList} > sym_to_del.tmp)
     
    i=0
    while read hgBranch; do
      hgBranches[$i]=${hgBranch}
      i=$((i+1))
    done <${hgBranchList}
     
    i=0
    while read str; do
      strToDel[$i]=${str}
      i=$((i+1))
    done < ./sym_to_del.tmp
     
    for i in ${!strToDel[@]}
    do
      echo ${hgBranches[$i]} | sed "s/${strToDel[$i]}//" >> result.tmp
    done
     
    sed -i 's/[ \t]*$//' result.tmp
    sed 's/^/"/g' result.tmp > branches_hg
    sed -i 's/$/"/g' branches_hg
    sed 's/ /-/g' result.tmp > branches_git
    sed -i 's/-\/-/\//g' branches_git
    sed -i 's/-\//\//g' branches_git
    sed -i 's/\/-/\//g' branches_git
    sed -i 's/---/-/g' branches_git
    sed -i 's/--/-/g' branches_git
    rm sym_to_del.tmp
    rm result.tmp
    
  4. #!/usr/bin/env bash
    gitBranchList="./branches_git"
    hgBranchList="./branches_hg"
    hgRepo="/repos/reponame"
     
    i=0
    while read hgBranch; do
      hgBranches[$i]=${hgBranch}
      i=$((i+1))
    done <${hgBranchList}
     
    i=0
    while read gitBranch; do
      gitBranches[$i]=${gitBranch}
      i=$((i+1))
    done <${gitBranchList}
     
    cd ${hgRepo}
    for i in ${!gitBranches[@]}
    do
      hg bookmark -r "${hgBranches[$i]}" "${gitBranches[$i]}-cnv"
    done
     
    hg push git+ssh://git@bitbucket.org:username/reponame-temp.git
    echo "Done."
    
  5. #!/bin/bash
    # clone repo, run git branch -a, delete remotes/origin words to leave only branch names, delete -cnv postfix, delete default branch string because we can't delete it
    repo="/repos/repo"
    gitBranchList="./branches_git"
    defaultBranch="default-cnv"
    while read gitBranch; do   gitBranches[$i]=${gitBranch};   i=$((i+1)); done < $gitBranchList
    cd $repo
    for i in ${!gitBranches[@]}; do git checkout ${gitBranches[$i]}-cnv; done
    git checkout $defaultBranch
    for i in ${!gitBranches[@]}; do
        git branch -m ${gitBranches[$i]}-cnv ${gitBranches[$i]}
        git push origin :${gitBranches[$i]}-cnv ${gitBranches[$i]}
        git push origin -u ${gitBranches[$i]}
    done
    
  6. #!/bin/bash
    # clone repo, run git branch -a, delete remotes/origin words to leave only branch names, delete -cnv postfix, delete default branch string because we can't delete it
    repo="/repos/repo"
    gitBranchList="./branches_git"
    defaultBranch="default"
    while read gitBranch; do   gitBranches[$i]=${gitBranch};   i=$((i+1)); done < $gitBranchList
    cd $repo
    for i in ${!gitBranches[@]}; do
        git checkout ${gitBranches[$i]}
        sed -i '1d' .hgignore
        mv .hgignore .gitignore
        git add .
        git commit -m "Migrated ignore file"
    done
    

我将尝试解释某些操作的含义,即使用中间存储库。最初,在转换后的存储库中,分支名称包含后缀“ -cnv”。这是由于hg书签功能。您需要删除此后缀,并且还要制作gitignore文件而不是hgignore。所有这些都增加了历史记录,因此增加了存储库的大小(并且不合理地增加了)。作为另一个示例,我可以引用以下内容:尝试创建一个存储库,并将第一次提交及其代码推送到300M。然后将其添加到gitignore中,并在没有它的情况下进行推送。他将保持历史。现在尝试将其从历史记录中删除(git filter-branch)。使用一定数量的提交,结果存储库的大小不会减少,但会增加。这可以通过优化解决,但是不能在bitbucket上启动。仅在导入存储库时执行。因此,所有的粗略操作都是在中间进行的,然后导入到新的操作中。最终,中间存储库的大小为1.15G,生成的结果为350M。 

结论


整个迁移过程分为几个阶段,即:

  • 准备(使用一个构建,软件安装,存储库转换,更新现有ccnet配置的示例向客户演示);
  • 开发环境及其测试的CI / CD配置(旧系统仍可并行运行);
  • 剩余环境的CI / CD设置(与现有的“良好”并行)和测试;
  • 迁移开发,暂存和测试;
  • 迁移生产并将域从旧的IIS实例转移到新的实例。

当前正在完成对成功完成的准备阶段的描述。除了现有系统没有崩溃并且git中的mercurial存储库已迁移以外,这里没有取得巨大的成功。但是,如果不对这些过程进行描述,就不会有更多技术部分的内容。下一部分将描述基于团队合作性建立CI系统的过程。

All Articles