如何使用 gitlab-runner 進行 Pipeline Debug

安裝 gitlab-runner 的部分可以參考此篇文章,這邊就直接針對如何透過 gitlab-runner 指令來執行 .gitlab-ci.yml 特定的 pipeline 進行測試。

> cat .gitlab-ci.yml
...
Test elasticsearch on 6.x:
  stage: integration
  services:
   - name: elasticsearch:6.8.0
     alias: elasticsearch
  image: *image_ref56
  cache: *cache_ref56
  script:
      - make integration
  tags:
    - docker
...

從上面的 yaml 檔可以知道有一個 “Test elasticsearch on 6.x” 的 Pipeline ,而透過 gitlab-runner 指令可以直接模擬 Gitlab-CI 來執行這個 pipeline 。

> gitlab-runner exec docker --cache-shared --docker-privileged --docker-cache-dir /cache --builds-dir /builds --docker-privileged --docker-volumes /home/xxx/var/gitlab-runner/builds:/builds --docker-volumes /home/xxx/cache:/cache --docker-volumes /home/xxx/.ssh:/root/.ssh --docker-volumes /var/run/docker.sock:/var/run/docker.sock 'Test elasticsearch on 6.x'

就會看到與 Gitlab-CI 上一樣的執行結果了,上面的指定目錄再麻煩各位依照自己的環境進行調整。

此時想說有沒有可能在不進行 git push 的狀況下,也能透過 gitlab-runner 模擬 Gitlab-CI 的執行結果呢?

然而在我修改程式碼之後馬上執行了上面的指令,卻執行尚未修改前的程式,這是怎麼回事? gitlab-runner 有提供一個 --debug 的參數可以使用,或許可以發現些線索。

> gitlab-runner --debug exec docker --cache-shared --docker-privileged --docker-cache-dir /cache --builds-dir /builds --docker-privileged --docker-volumes /home/xxx/var/gitlab-runner/builds:/builds --docker-volumes /home/xxx/cache:/cache --docker-volumes /home/xxx/.ssh:/root/.ssh --docker-volumes /var/run/docker.sock:/var/run/docker.sock 'Test elasticsearch on 6.x'

...
Executing on /runner--project-0-concurrent-0-predefined-1 the #!/usr/bin/env bash

set -eo pipefail
set +o noclobber
: | eval $'export FF_CMD_DISABLE_DELAYED_ERROR_LEVEL_EXPANSION=$\'false\'\nexport FF_USE_LEGACY_BUILDS_DIR_FOR_DOCKER=$\'false\'\nexport FF_USE_LEGACY_VOLUMES_MOUNTING_ORDER=$\'false\'\nexport CI_RUNNER_SHORT_TOKEN=\'\'\nexport CI_BUILDS_DIR=$\'/builds\'\nexport CI_PROJECT_DIR=$\'/builds/0/project-0\'\nexport CI_CONCURRENT_ID=0\nexport CI_CONCURRENT_PROJECT_ID=0\nexport CI_SERVER=$\'yes\'\nexport CI=$\'true\'\nexport GITLAB_CI=$\'true\'\nexport CI_SERVER_NAME=$\'GitLab CI\'\nexport CI_SERVER_VERSION=\'\'\nexport CI_SERVER_REVISION=\'\'\nexport CI_PROJECT_ID=0\nexport CI_JOB_ID=1\nexport CI_JOB_NAME=$\'Test elasticsearch on 5.x\'\nexport CI_JOB_STAGE=$\'integration\'\nexport CI_JOB_TOKEN=\'\'\nexport CI_REPOSITORY_URL=$\'/home/xxx/repo/project-a\'\nexport CI_COMMIT_SHA=$\'74cd6c29f235b8be115fd54f97a163025ac49dfe\'\nexport CI_COMMIT_BEFORE_SHA=$\'88c146a08a8ed3cc6bc41b023ff064ea7d2c3b28\'\nexport CI_COMMIT_REF_NAME=$\'feature/boost-from-query\'\nexport COMPOSER_HOME=$\'/cache/composer\'\nexport CI_DISPOSABLE_ENVIRONMENT=$\'true\'\nexport CI_RUNNER_VERSION=$\'12.6.0~beta.2048.g59f07d78\'\nexport CI_RUNNER_REVISION=$\'59f07d78\'\nexport CI_RUNNER_EXECUTABLE_ARCH=$\'linux/amd64\'\nexport GIT_LFS_SKIP_SMUDGE=1\n$\'rm\' "-r" "-f" "/builds/0/project-0"\necho $\'\\x1b[32;1mFetching changes...\\x1b[0;m\'\n$\'mkdir\' "-p" "/builds/0/project-0.tmp/git-template"\n$\'git\' "config" "-f" "/builds/0/project-0.tmp/git-template/config" "fetch.recurseSubmodules" "false"\n$\'git\' "init" "/builds/0/project-0" "--template" "/builds/0/project-0.tmp/git-template"\n$\'cd\' "/builds/0/project-0"\n$\'rm\' "-f" ".git/index.lock"\n$\'rm\' "-f" ".git/shallow.lock"\n$\'rm\' "-f" ".git/HEAD.lock"\n$\'rm\' "-f" ".git/hooks/post-checkout"\nif $\'git\' "remote" "add" "origin" "/home/xxx/repo/project-a" >/dev/null 2>/dev/null; then\n  echo $\'\\x1b[32;1mCreated fresh repository.\\x1b[0;m\'\nelse\n  $\'git\' "remote" "set-url" "origin" "/home/xxx/repo/project-a"\nfi\n$\'git\' "fetch" "origin" "--prune"\necho $\'\\x1b[32;1mChecking out 74cd6c29 as feature/boost-from-query...\\x1b[0;m\'\n$\'git\' "checkout" "-f" "-q" "74cd6c29f235b8be115fd54f97a163025ac49dfe"\n$\'git\' "clean" "-ffdx"\nif $\'git\' "lfs" "version" >/dev/null 2>/dev/null; then\n  $\'git\' "lfs" "pull"\n  echo\nfi\necho $\'\\x1b[32;1mSkipping Git submodules setup\\x1b[0;m\'\n'
exit 0
...

後段可以看到一串指令將它整理一下。

Executing on /runner--project-0-concurrent-0-predefined-1 the #!/usr/bin/env bash

set -eo pipefail
set +o noclobber
: | eval $'
export FF_CMD_DISABLE_DELAYED_ERROR_LEVEL_EXPANSION=$\'false\'
export FF_USE_LEGACY_BUILDS_DIR_FOR_DOCKER=$\'false\'
export FF_USE_LEGACY_VOLUMES_MOUNTING_ORDER=$\'false\'
export CI_RUNNER_SHORT_TOKEN=\'\'
export CI_BUILDS_DIR=$\'/builds\'
export CI_PROJECT_DIR=$\'/builds/0/project-0\'
export CI_CONCURRENT_ID=0
export CI_CONCURRENT_PROJECT_ID=0
export CI_SERVER=$\'yes\'
export CI=$\'true\'
export GITLAB_CI=$\'true\'
export CI_SERVER_NAME=$\'GitLab CI\'
export CI_SERVER_VERSION=\'\'
export CI_SERVER_REVISION=\'\'
export CI_PROJECT_ID=0
export CI_JOB_ID=1
export CI_JOB_NAME=$\'Test elasticsearch on 5.x\'
export CI_JOB_STAGE=$\'integration\'
export CI_JOB_TOKEN=\'\'
export CI_REPOSITORY_URL=$\'/home/ubuntu/repo/project-a\'
export CI_COMMIT_SHA=$\'74cd6c29f235b8be115fd54f97a163025ac49dfe\'
export CI_COMMIT_BEFORE_SHA=$\'88c146a08a8ed3cc6bc41b023ff064ea7d2c3b28\'
export CI_COMMIT_REF_NAME=$\'feature/boost-from-query\'
export COMPOSER_HOME=$\'/cache/composer\'
export CI_DISPOSABLE_ENVIRONMENT=$\'true\'
export CI_RUNNER_VERSION=$\'12.6.0~beta.2048.g59f07d78\'
export CI_RUNNER_REVISION=$\'59f07d78\'
export CI_RUNNER_EXECUTABLE_ARCH=$\'linux/amd64\'
export GIT_LFS_SKIP_SMUDGE=1\n$\'rm\' "-r" "-f" "/builds/0/project-0"\necho $\'\\x1b[32;1mFetching changes...\\x1b[0;m\'\n$\'mkdir\' "-p" "/builds/0/project-0.tmp/git-template"\n$\'git\' "config" "-f" "/builds/0/project-0.tmp/git-template/config" "fetch.recurseSubmodules" "false"\n$\'git\' "init" "/builds/0/project-0" "--template" "/builds/0/project-0.tmp/git-template"\n$\'cd\' "/builds/0/project-0"\n$\'rm\' "-f" ".git/index.lock"\n$\'rm\' "-f" ".git/shallow.lock"\n$\'rm\' "-f" ".git/HEAD.lock"\n$\'rm\' "-f" ".git/hooks/post-checkout"\nif $\'git\' "remote" "add" "origin" "/home/xxx/repo/project-a" >/dev/null 2>/dev/null; then\n  echo $\'\\x1b[32;1mCreated fresh repository.\\x1b[0;m\'\nelse\n  $\'git\' "remote" "set-url" "origin" "/home/ubuntu/repo/project-a"\nfi\n$\'git\' "fetch" "origin" "--prune"\necho $\'\\x1b[32;1mChecking out 74cd6c29 as feature/boost-from-query...\\x1b[0;m\'\n$\'git\' "checkout" "-f" "-q" "74cd6c29f235b8be115fd54f97a163025ac49dfe"\n$\'git\' "clean" "-ffdx"\nif $\'git\' "lfs" "version" >/dev/null 2>/dev/null; then\n  $\'git\' "lfs" "pull"\n  echo\nfi\necho $\'\\x1b[32;1mSkipping Git submodules setup\\x1b[0;m\'\n'
exit 0

其中 GIT_LFS_SKIP_SMUDGE 環境參數後面執行的指令這邊吸引了我,將他整理一下…

> rm -rf /builds/0/project-0
> echo git-template
> $git config -f /builds/0/project-0.tmp/git-template/config fetch.recurseSubmodules false
> $git init /builds/0/project-0 --template /builds/0/project-0.tmp/git-template
> cd /builds/0/project-0
> rm -f .git/index.lock
> rm -f .git/shallow.lock
> rm -f .git/HEAD.lock
> rm -f .git/hooks/post-checkout
> if 
    $git remote add origin /home/xxx/repo/project-a >/dev/null 2>/dev/null;
then
    echo $\\x1b[32;1mCreated fresh repository.\\x1b[0;m
else
    $git remote set-url origin /home/xxx/repo/project-a
fi
> $git fetch origin --prune
> echo \\x1b[32;1mChecking out 74cd6c29 as feature/boost-from-query...\\x1b[0
> $git checkout -f -q 74cd6c29f235b8be115fd54f97a163025ac49dfe
> $git clean -ffdx
> if
    $git lfs version >/dev/null 2>/dev/null;
then
    $git lfs pull
fi
> echo \\x1b[32;1mSkipping Git submodules setup\\x1b[0;m

其中可以看到在設定 git remote 路徑的時候,他是抓取實體專案路徑,也就是說,如果 code change 沒有下 git commit 就無法讓 runner 抓取到,這下簡單了,只要 git commit 就好… 測試後確認成功。

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *