我有一个名为“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 theLAST_SEEN_COMMIT_FILE
.I wonder if it is possible to determine the
LAST_SEEN_COMMIT
with a script?
Let's say for example, thedeploy
job only gets created when a branch merges tomaster
branch ofsource-repo
and there are changes to files insource-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/