代码之家  ›  专栏  ›  技术社区  ›  Aleksander Wons

在本地和GitHub Actions中运行Make时处理的不同变量

  •  1
  • Aleksander Wons  · 技术社区  · 5 月前

    我有以下GitHub工作流程:

    name: Makefile test
    on:
      push:
    env:
      MY_SECRET_NAME: ${{ secrets.MY_SECRET_NAME }}
    jobs:
      test-job:
        runs-on: ubuntu-latest
        steps:
          - name: Checkout
            uses: actions/checkout@v4
          - name: Test makefile
            run: make build
    

    这是执行的makefile:

    .PHONY: build
    build:
        rm -f my_secret.txt
        docker build --no-cache --progress plain --debug -t ci:latest -f Dockerfile --secret id=MY_SECRET_NAME .
        $(eval IMAGE_ID=$(shell docker create ci:latest))
        docker cp "${IMAGE_ID}:/tmp/my_secret.txt" my_secret.txt
        cat my_secret.txt
    

    这是Dockerfile:

    FROM alpine:latest
    
    WORKDIR /tmp
    
    RUN --mount=type=secret,id=MY_SECRET_NAME \
        echo $(cat /run/secrets/MY_SECRET_NAME) > /tmp/my_secret.txt
    

    跑步时 MY_SECRET_NAME=123 make build 在本地,我得到了正确的结果:文件 my_secret.txt 包含预期值(我在Ubuntu上运行它并从zsh触发它)。

    当我在GitHub Actions上运行上述工作流时,我收到以下错误:

    docker cp ":/tmp/my_secret.txt" my_secret.txt
    must specify at least one container source
    make: *** [Makefile:8: build] Error 1
    

    我的问题:为什么变量 IMAGE_ID 没有在GitHub Actions上设置,但它在本地运行良好吗?我的印象是 make 使用 sh 除非另有说明。

    1 回复  |  直到 5 月前
        1
  •  2
  •   MadScientist    5 月前

    这是错误的:

    build:
            rm -f my_secret.txt
            docker build --no-cache --progress plain --debug -t ci:latest -f Dockerfile --secret id=MY_SECRET_NAME .
            $(eval IMAGE_ID=$(shell docker create ci:latest))
            docker cp "${IMAGE_ID}:/tmp/my_secret.txt" my_secret.txt
            cat my_secret.txt
    

    这里有一个编写makefile的提示:使用它总是错误的 $(eval ...) $(shell ...) 食谱内(1)

    makefile配方已经是一个shell,所以你不需要 shell .还有 eval 用于修改make对makefile的内部理解,这在配方中是不应该做的。

    当make要运行一个食谱时,它首先会扩展 整个食谱 包括所有线路。在这种情况下,这意味着你 eval 被调用 之前 任何 命令,包括 docker build 命令被执行。

    在编写食谱时,您应该始终使用shell操作,如下所示:

    build:
            rm -f my_secret.txt
            docker build --no-cache --progress plain --debug -t ci:latest -f Dockerfile --secret id=MY_SECRET_NAME .
            docker cp "$$(docker create ci:latest):/tmp/my_secret.txt" my_secret.txt
            cat my_secret.txt
    

    (1) 实际上,在非常罕见、非常模糊、非常复杂的情况下,您可能需要使用 eval 在食谱中,但除非你是一个真正的 make maven和极其复杂的构建环境,你永远不应该这样做。