65.9K
CodeProject 正在变化。 阅读更多。
Home

通过 GitLab CI 构建/部署 Jekyll 和 Hugo 网站

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2021 年 7 月 21 日

CPOL

3分钟阅读

viewsIcon

5418

在通过 Bitbucket Pipelines 和 GitHub Actions 自动部署 Jekyll 网站之后,我也想通过 GitLab CI 尝试同样的事情

我还有一个 Jekyll 网站,它位于一个私有的 Mercurial 存储库中,无论如何我都需要将其移出 Bitbucket,所以我将其转换为 Git 并将其推送到 GitLab(去年就已经做了)。此外,我想尝试 Hugo 作为 Jekyll 的替代方案,主要因为它速度快(Jekyll 构建速度慢)。我已经 在这里写过 - 我的实际测试网站(不是我在帖子中链接的演示)在另一个私有的 GitLab 存储库中,我也想为它设置 CI。

必备组件

与之前帖子中使用的存储库完全一样,现有 Jekyll 网站的大部分“构建和部署逻辑”都在两个 shell 脚本中,并且我为 Hugo 测试网站使用了相同的模式

  • ci-build.sh 执行 Jekyll/Hugo 从源代码构建网站,压缩结果并保存该文件作为 GitLab CI 构建工件
  • ci-deploy.sh 解压缩网站并将其复制到 web 服务器上的正确目录
  • GitLab CI 创建与 web 服务器的 SSH 连接并 直接在 web 服务器上 执行 ci-deploy.sh

有关所有这些的更详尽的解释,请阅读之前的两篇 文章 文章

在这篇文章中,我将重点介绍 GitLab 特有的内容。

第 1A 部分:构建 Jekyll 网站

与 Bitbucket Pipelines 类似,GitLab CI 可以指定一个 Docker 镜像,然后将执行实际的构建。

这是 .gitlab-ci.yml 的相关部分

build:
  only:
  - master
  stage: build
  image: jekyll/builder
  script:
  - chmod +x ci-build.sh
  - ./ci-build.sh
  artifacts:
    paths:
    - build
    expire_in: 1 week

... 这是 ci-build.sh

#!/bin/bash
jekyll build 
if [ $? -ne 0 ]
then
  exit 1
fi

mkdir build

tar -czvf build/build.tar.gz -C _site .

shell 脚本创建的 build 目录被 GitLab CI 保存为工件(因为它在部署步骤中需要),但一周后过期(因为一旦部署了,我们就不再需要它)。

第 1B 部分:构建 Hugo 网站

与 Jekyll 相同... 除了我们使用 monachus/hugo 镜像,它就像 jekyll/builder,但用于 Hugo

.gitlab-ci.yml:

build:
  only:
  - master
  stage: build
  image: monachus/hugo
  script:
  - chmod +x ci-build.sh
  - ./ci-build.sh
  artifacts:
    paths:
    - build
    expire_in: 1 week

ci-build.sh

#!/bin/bash

cd web
rm -r _site
hugo
if [ $? -ne 0 ]
then
  exit 1
fi
cd ..

mkdir build
tar -czvf build/build.tar.gz -C ./web/_site .

第 2 部分:通过 SSH 部署到 web 服务器

从“有多难才能让它工作”的角度来看,GitLab 位于中间。

它不像 Bitbucket 那么容易,您只需要将您的 SSH 密钥粘贴到 Web UI 中,并且实际的 SSH voodoo 就会在后台自动发生。

与 GitHub Actions 类似,GitLab CI 需要在 .yml 中使用几行脚本来设置 SSH,但至少他们在 文档中有一个完整的示例,您只需要复制并粘贴。

在撰写本文时,它是

before_script:
  - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
  - eval $(ssh-agent -s)
  - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
  - mkdir -p ~/.ssh
  - chmod 700 ~/.ssh

这假设基于 Debian 的镜像,但我使用的是 Linux Alpine,所以我需要修改 apt-get 部分,因为我从 在 Bitbucket 中设置 CI 中已经知道,在 Alpine 中,apt-getapk

对于 Jekyll 和 Hugo,我在 .gitlab-ci.yml 中使用这部分

deploy:
  only:
  - master
  stage: deploy
  image: alpine
  before_script:
  - apk update && apk add openssh-client git openssh rsync
  - eval $(ssh-agent -s)
  - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
  - mkdir -p ~/.ssh
  - chmod 700 ~/.ssh
  - ssh-keyscan $DOMAIN >> ~/.ssh/known_hosts
  - chmod 644 ~/.ssh/known_hosts
  script:
  - rsync -rSlh --stats build/ ssh-$WEB_USER@$DOMAIN:$WEBPATH
  - ssh -o StrictHostKeyChecking=yes ssh-$WEB_USER@$DOMAIN 'bash -s' -- < ci-deploy.sh $WEBPATH

与 Bitbucket 和 GitHub 类似,变量来自 GitLab 上存储库的 CI 设置 (https://gitlab.com/USERNAME/REPO/-/settings/ci_cd#js-cicd-variables-settings)

$DOMAIN 是一个来自我的 .gitlab-ci.yml 的“局部变量”(我不想将其作为变量放入设置中,因为它实际上不是秘密)

variables:
  DOMAIN: example.com

ci-deploy.sh 对于 Jekyll 和 Hugo 都是一样的

#!/bin/bash
rm -rf $1/tmp
mkdir $1/tmp
tar -xzvf $1/build/build.tar.gz -C $1/tmp
rsync -Pav --delete $1/tmp/ $1/web

最终想法

到目前为止,这是我的“使用 CI 提供商 X 部署静态站点”系列的最后一部分 - 现在我尝试了所有我想尝试的提供商。 :-)

最后,您使用哪个可能并不重要。如果您像我一样是 Shell/SSH 新手,您会花费大部分时间来弄清楚这部分... 无论您使用哪个提供商。一旦您弄清楚了它,并且需要使用同一个 CI 提供商部署另一个站点,那么它基本上就是复制和粘贴。

© . All rights reserved.