【问题标题】:How to Deploy an already existing Gitlab release without building the project again?如何在不重新构建项目的情况下部署已经存在的 Gitlab 版本?
【发布时间】:2021-09-14 23:27:40
【问题描述】:

我有一个整洁的 Gitlab 管道,它包含 5 个阶段和 >10 个作业,用于在多个环境中测试、构建、发布和部署结果。

有时,我们需要将一个环境回滚到旧版本。使用 Jenkins,这很容易通过额外的工作完成,只需从存储库中部署现有版本,而无需再次构建项目。

在 Gitlab 上,似乎我要么必须使用它自己的构建管道创建一个新项目,仅用于部署,要么在每个作业中添加一个 rule,上面写着 不要运行构建和测试作业,但是只有设置了环境变量 DEPLOY_OLD_RELEASE 时的部署作业

我不喜欢任何一种方式,因为仅为构建管道创建一个项目似乎是一项巨大的开销,并且修改所有作业是一项巨大的工作并且不容易维护。

【问题讨论】:

    标签: gitlab-ci continuous-deployment


    【解决方案1】:

    一旦 Gitlab 作业通过,您可以多次重新运行它。例如,如果您有一个部署作业,将 scp 的 tar 文件发送到远程服务器,使用 ssh 进行提取、移动到特定目录、更改符号链接等。您只需重新运行该特定作业即可。

    但是,由于听起来您有一个定义良好的管道,因此 tar 文件很可能不是在您的部署作业中构建的,而是类似“打包应用程序”作业的一个。在此作业中,您可以将最终的 tar 文件作为工件上传,以便您的部署作业可以部署它。

    如果是这种情况,只要您的“打包”作业的工件仍然存在(因为它们根据服务器的默认设置或您在作业定义中指定的时间到期),您可以简单地重新运行 Deploy工作。但是,如果这些工件已过期,您将不得不重新运行 Package 作业,然后是 Deploy 作业。

    但是,您的“包”作业可能依赖于该作业中未构建的一些依赖项,例如运行 npm cicomposer install(用于 PHP 项目)。如果这些活动在之前阶段的其他作业中发生并作为“包”作业使用的工件上传,您可能还必须重新运行这些活动。

    这听起来可能需要重新运行大量作业,但如果您为自己的目的准确设置了过期时间,那还不错。例如,我的“构建”作业(那些安装 npm 依赖项等的)在 30 分钟内到期,因为“包”作业将在这些作业完成后立即运行,我再也不需要它们了。相反,我将我的“包”作业工件保留 2 周,以便我可以相对快速地重新部署而无需重新构建依赖项。

    根据我使用应用程序的经验,我几乎从不重新部署超过 2 周的构建,因为通常会有更新的构建来替换它。但是,您应该调整每个项目的过期时间。

    这是一个类似于我在项目中使用的管道定义作为示例。这是一个带有 JS/Vue 前端的 PHP 后端项目,因此大多数工作都不会适用,但会给你一个很好的思路。​​

    stages:
      - build
      - package
      - deploy
    
    Run Composer Install:
      stage: build
      image: composer:latest
      only:
        - tags
      needs: []
      before_script:
        - echo ${COMPOSER_AUTH_JSON} > auth.json
      script:
        - composer clearcache; composer self-update --2
        - php -d memory_limit=-1 /bin/composer install --ignore-platform-reqs --no-dev
      artifacts:
        paths:
          - vendor
        when: on_success
        expire_in: 30 minutes
    
    Npm Install:
      stage: build
      image: hub.comcast.net/code_common/spa_site_7.4:5
      only:
        - branches
        - tags
      needs: []
      script:
        - /usr/bin/npm ci
      artifacts:
        paths:
          - node_modules
        when: on_success
        expire_in: 30 minutes
    
    Package Application:
      stage: package
      image: ... #same situation as the Package job for int environment
      dependencies:
        - Run Composer Install
        - Npm Install
      needs: ["Npm Install", "Run Composer Install"]
      only:
        - tags
      script:
        - npm run build
        - rm -rf .git* Vagrantfile vagrant_files .env.example .env.local CONTRIBUTING.md build.xml
        - mkdir -p bootstrap/cache
        - chmod -R go+r ./*
        - find ./ -type d -exec chmod ugo+x {} \;
        - php artisan package:discover
        - php artisan optimize
        - tar -C ../ --exclude "$CI_PIPELINE_ID.tar.gz" -zcpf $CI_PIPELINE_ID.tar.gz --warning=no-file-changed $(basename $CI_PROJECT_DIR) || [[ $? -eq 1 ]]
      artifacts:
        paths:
        - $CI_PIPELINE_ID.tar.gz
        when: on_success
        expire_in: 30 days
    
    Deploy:
      stage: deploy
      image: my_image
      needs: ["Package Application"]
      dependencies: ["Package Application"]
      script:
        - ./deploy_placeholder.sh
    

    前三个作业针对多个环境运行构建步骤。接下来,我获取之前作业中上传的工件,运行npm run build 之类的东西,并最终创建作为工件上传的 .tar.gz 文件。最后,Deploy 作业拉下 .tar.gz 文件并进行部署。

    使用此层次结构,根据初始部署和重新部署之间经过的时间,您只需要重新运行几个作业,只需为每个作业按下一个按钮即可。

    【讨论】:

    • 感谢您的详细回答,这对我帮助很大。我只是不知道如何正确使用expire_in 以及重新运行作业。现在我只需将发布的版本存储在工件文件version 中,并将其保存在4 weeks 中。我的部署作业只需要 version 工件来部署正确的版本,并且可以在构建后最多 4 周内触发!
    • 太好了,很高兴我能帮上忙!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-28
    • 2011-12-04
    • 1970-01-01
    • 2016-12-21
    • 2016-10-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多