gitlab - 将 Gitmodules 与 GitLab CI 结合使用不起作用

标签 gitlab gitlab-ci cicd

我有一个名为“pipelines”的存储库,其中有一个 .gitlab-ci.yml 文件,该文件运行脚本来执行特定任务。

我使用存储库镜像从“管道”存储库中提取内容。

管道中的作业克隆一个名为“source-repo”的存储库,并在该存储库目录中运行命令。

.gitlab-ci.yml

variables:
  GIT_SUBMODULE_STRATEGY: recursive

.maven:
    image:
      image: maven:3.6.3-jdk-11
      entrypoint: [""]
      
deploy:
  extends: .maven
  stage: deploy
  script: |
    mkdir -p /root/.ssh
    echo "${KNOWN_HOSTS}" > /root/.ssh/known_hosts
    chmod 600 /root/.ssh/known_hosts
    echo "${AUTH_KEY}" >  /root/.ssh/id_rsa
    chmod 600  /root/.ssh/id_rsa
    
    git clone -b master ssh://<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5f38362b1f38362b713c30322f3e3126713c3032" rel="noreferrer noopener nofollow">[email protected]</a>:7999/projects/source-repo.git

    cd source-repo && mvn package

我想向作业添加规则,以便我可以控制何时创建管道作业。
例如,只有当有更改推送到“source-repo”时,才应创建“deploy”作业。

为了实现这一目标,我尝试了以下方法:

deploy:
  extends: .maven
  stage: deploy
  script: |
    cd source-repo && mvn package
  rules:
     - changes:
       - source-repo/

它不起作用,因为 source-repo 是一个单独的存储库。因此,我尝试 .gitmodules 将“source-repo”作为子目录添加到“pipeline”存储库中。

[submodule "source-repo"]
  path = source-repo
  url = https://git.company.com/scm/projects/cat-source.git   

但是,我还是没能成功。我有什么遗漏的吗?

最佳答案

changes keyword用于识别配置 CI/CD 管道的同一存储库中文件的更改,并且它无法跟踪单独存储库中的更改,即使将其添加为子模块也是如此。

Submodules in Git是指向另一个存储库中特定提交的指针。 .gitmodules 文件保存有关子模块的信息,例如路径和 URL。但是,即使您将“source-repo”作为“管道”存储库中的子模块包含在内,GitLab CI/CD 仍然会识别“管道”存储库文件方面的更改,而不是动态地基于“source-repo”子模块的文件。


为了实现您想要做的事情(即根据“source-repo”中的更改触发“部署”作业),您必须在“source-repo”存储库本身,而不是尝试从“pipelines”存储库控制它。这样,您就可以利用 changes 关键字来有效监控“source-repo”存储库中的更改并相应地触发作业。


但是,如果无法在“source-repo”中设置 CI/CD 管道,并且您必须控制“pipelines”存储库中的所有内容,则可能需要创建一个在决定是否运行“deploy”作业之前检查“source-repo”中的更改的脚本。

脚本可能看起来像这样(给出一个总体思路):

deploy:
  extends: .maven
  stage: deploy
  script: |
    # Your existing setup scripts here

    # Clone the source-repo to check for recent changes
    git clone -b master ssh://<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="66010f1226010f124805090b1607081f4805090b" rel="noreferrer noopener nofollow">[email protected]</a>:7999/projects/source-repo.git

    # Check for changes in the source-repo (this is a placeholder, you would add a script to check for real changes)
    CHANGE_DETECTED=$(./check_for_changes.sh) 

    if [ "$CHANGE_DETECTED" == "yes" ]; then
        cd source-repo && mvn package
    else
        echo "No changes detected in source-repo; skipping deploy job"
    fi

check_for_changes.sh 将是您创建的一个脚本,用于根据您的具体条件检查“source-repo”中的更改。如果检测到更改并且应该运行 deploy 作业,它应该打印“yes”,如果没有,则打印其他内容。

类似于:

#!/bin/bash

# Define the remote repository
REMOTE_REPO="ssh://<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7e19170a3e19170a501d11130e1f1007501d1113" rel="noreferrer noopener nofollow">[email protected]</a>:7999/projects/source-repo.git"

# Define a file to store the last seen commit hash
LAST_SEEN_COMMIT_FILE="last_seen_commit.txt"

# Fetch the latest commit hash from the remote repository
LATEST_COMMIT=$(git ls-remote $REMOTE_REPO HEAD | awk '{ print $1}')

# Check if the LAST_SEEN_COMMIT_FILE exists and has a value
if [ -f $LAST_SEEN_COMMIT_FILE ]; then
    LAST_SEEN_COMMIT=$(cat $LAST_SEEN_COMMIT_FILE)
else
    LAST_SEEN_COMMIT=""
fi

# Compare the latest commit hash with the last seen commit hash
if [ "$LATEST_COMMIT" != "$LAST_SEEN_COMMIT" ]; then
    # If they are different, update the last seen commit hash file and return "yes"
    echo $LATEST_COMMIT > $LAST_SEEN_COMMIT_FILE
    echo "yes"
else
    # If they are the same, return "no"
    echo "no"
fi

This is a nice approach.

However, if I use as a script like check_for_changes.sh, then I have to manually pass the last commit that I want to compare with the latest commit to the LAST_SEEN_COMMIT_FILE.

I wonder if it is possible to determine the LAST_SEEN_COMMIT with a script?
Let's say for example, the deploy job only gets created when a branch merges to master branch of source-repo and there are changes to files in source-repo.

您可以修改脚本以根据特定条件自动确定LAST_SEEN_COMMIT
要识别最近一次合并到 master 分支之前发生的最后一次提交,您可以使用 Git 命令查找最近的合并提交,然后找到其父提交(这将是之前的提交)合并)。

新的和修改后的 check_for_changes.sh 脚本用于查找最近合并之前 master 分支上的最后一次提交:

#!/bin/bash

# Define the remote repository
REMOTE_REPO="ssh://<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c0a7a9b480a7a9b4eea3afadb0a1aeb9eea3afad" rel="noreferrer noopener nofollow">[email protected]</a>:7999/projects/source-repo.git"

# Clone the remote repository to a temporary directory
TEMP_DIR=$(mktemp -d)
git clone $REMOTE_REPO $TEMP_DIR

# Find the hash of the most recent merge commit on the master branch
cd $TEMP_DIR
git checkout master
LAST_MERGE_COMMIT=$(git log --merges -n 1 --pretty=format:"%H")

# Find the hash of the commit before the most recent merge commit (parent commit)
LAST_SEEN_COMMIT=$(git log --pretty=format:"%H" -n 1 $LAST_MERGE_COMMIT^)

# Clean up by removing the temporary directory
cd ..
rm -rf $TEMP_DIR

# Print the hash of the last seen commit (before the most recent merge)
echo $LAST_SEEN_COMMIT

我将 source-repo 克隆到临时目录,并使用带有标志的 git log 来查找 master 上的最新合并提交> 分支机构。
我再次使用 git log 与合并提交的父级 ($LAST_MERGE_COMMIT^) 来查找合并之前的提交。

在您的 .gitlab-ci.yml 中,您将调用此脚本来获取 LAST_SEEN_COMMIT,然后继续执行其余逻辑以检查自此以来的更改此提交并决定是否运行部署作业。
请注意,此脚本会查找最近一次合并到 master 之前的最后一次提交,无论特定文件是否已更改;如果需要,您可能需要添加更多逻辑来检查特定文件的更改。

关于gitlab - 将 Gitmodules 与 GitLab CI 结合使用不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77085607/

相关文章:

Gitlab 删除旧提交

git - 克隆后记住多个 git 远程 url

azure - 从管道 B 访问管道 A 的变量... Azure Devops

Azure Pipeline 在触发器路径中使用星号包括

linux - 如何正确设置Gitlab gitlab-ci变量

gitlab - 是否可以限制开发者不在gitlab中创建分支?只有所有者或维护者才能创建

android - CI Android项目-gradlew没有此类文件

gitlab-ci - 添加 .gitlab-ci.yml 文件不会激活 CI

Gitlab runner 在完成之前开始另一项工作

google-cloud-platform - 允许未经身份验证的参数不起作用