如何从文件内容设置变量?及Git检测除SRCREV变更外的重要变更
解决方案
一、从文件内容设置变量
1. Shell 脚本/本地环境
直接通过命令替换读取文件内容赋值:
# 读取文件内容到变量 SRCREV_MYPKG=$(cat ./path/to/mypkg-sha.txt) # 更高效的写法(适配bash/zsh) SRCREV_MYPKG=$(< ./path/to/mypkg-sha.txt)
2. BitBake 配方中设置 SRCREV
在自有包的配方(.bb/.bbappend)中,用BitBake内置函数读取文件中的SHA值:
# 假设SHA文件与配方同目录,可通过FILE_DIRNAME定位 SRCREV = "${@bb.utils.read_file(d.getVar('FILE_DIRNAME') + '/mypkg-sha.txt').strip()}"
3. GitLab CI 中传递环境变量
在CI阶段读取文件内容,通过dotenv artifact传递给后续job:
variables: SHA_FILE: "./path/to/mypkg-sha.txt" stages: - prepare - build prepare_sha: stage: prepare script: - echo "SRCREV_MYPKG=$(cat $SHA_FILE)" >> variables.txt artifacts: reports: dotenv: variables.txt build_sdk: stage: build needs: [prepare_sha] script: - echo "Using SRCREV: $SRCREV_MYPKG" - # 执行SDK构建命令
二、检测Git非重大变更(排除SRCREV修改)
针对仅在自有包SRCREV变更以外的场景触发SDK构建的需求,推荐以下两种简便方案:
方案1:分离SHA到独立文件(推荐)
将每个自有包的SHA值单独存放在独立文件(如mypkg-sha.txt),配方读取这些文件作为SRCREV。然后在CI中检查除这些SHA文件外的所有变更:
build_sdk: script: - # 获取变更文件列表,排除SHA文件 - CHANGED_FILES=$(git diff --name-only $CI_COMMIT_BEFORE_SHA $CI_COMMIT_SHA | grep -v -E '^path/to/sha-files/.*\.txt$') - # 检查第三方子模块变更(子模块变更需触发构建时启用) - SUBMODULE_CHANGES=$(git submodule status | grep -v '^ ') - # 存在非SHA文件变更或子模块变更则触发构建 - if [ -n "$CHANGED_FILES" ] || [ -n "$SUBMODULE_CHANGES" ]; then echo "检测到相关变更,开始构建SDK..." # 执行SDK构建命令 else echo "仅检测到SHA文件变更,跳过SDK构建。" exit 0 fi
方案2:直接过滤配方中的SRCREV行
无需调整现有文件结构,直接对配方文件的diff结果过滤SRCREV相关行,判断是否有其他变更:
build_sdk: script: - # 检查配方文件中除SRCREV外的变更 - RECIPE_CHANGES=$(git diff $CI_COMMIT_BEFORE_SHA $CI_COMMIT_SHA -- path/to/recipes/ | grep -v '^[+-]SRCREV' | grep -v '^@@' | grep -v '^diff --git') - # 检查非配方文件的变更 - OTHER_CHANGES=$(git diff --name-only $CI_COMMIT_BEFORE_SHA $CI_COMMIT_SHA | grep -v '^path/to/recipes/') - # 检查子模块变更 - SUBMODULE_CHANGES=$(git submodule status | grep -v '^ ') - # 任一条件满足则触发构建 - if [ -n "$RECIPE_CHANGES" ] || [ -n "$OTHER_CHANGES" ] || [ -n "$SUBMODULE_CHANGES" ]; then echo "检测到相关变更,开始构建SDK..." # 执行构建命令 else echo "仅检测到SRCREV变更,跳过构建。" exit 0 fi
方案3:GitLab CI Rules 原生判断
用rules结合changes规则快速过滤变更,适合简单场景:
build_sdk: script: - # 执行SDK构建命令 rules: - if: '$CI_PIPELINE_SOURCE == "push"' changes: - "**/*" - "!path/to/sha-files/*.txt" when: always - when: never
注意:该方式不直接支持子模块变更检测,若需包含子模块变更,需额外结合脚本判断。
总结
- 优先选择方案1,逻辑清晰易维护,diff检查简单,适配你最初的思路;
- 若不想调整现有配方结构,方案2可直接适配现有代码;
- GitLab CI原生
rules方式适合简单场景,但子模块变更需额外处理。
内容的提问来源于stack exchange,提问作者skyking
相关产品推荐
相关产品推荐

