Home > Net >  How to do string subsitution on env var in makefile script
How to do string subsitution on env var in makefile script

Time:12-22

I have a makefile with the following script:

build:
    DOCKER_BUILDKIT=1 docker build --build-arg GITHUB_ACTOR=${GITHUB_ACTOR} --build-arg GITHUB_TOKEN=${GITHUB_TOKEN} -t ${DOCKER_REGISTRY}/strick:${IMAGE_BRANCH}-${IMAGE_TAG} -t ${DOCKER_REGISTRY}/strick:${IMAGE_BRANCH}-latest .

and I just realized that when ${IMAGE_BRANCH] has a slash in it, like feature/a-b-c then the docker build step will fail. I'd like to create a new env var which replaces slashes in IMAGE_BRANCH with dashes.

I tried several variants including the following

build:
    CLEANED_IMAGE_BRANCH=$(echo ${IMAGE_BRANCH} | sed 's/\//-/g')
    DOCKER_BUILDKIT=1 docker build --build-arg GITHUB_ACTOR=${GITHUB_ACTOR} --build-arg GITHUB_TOKEN=${GITHUB_TOKEN} -t ${DOCKER_REGISTRY}/strick:${CLEANED_IMAGE_BRANCH}-${IMAGE_TAG} -t ${DOCKER_REGISTRY}/strick:${CLEANED_IMAGE_BRANCH}-latest .

and they all seemed to fail because CLEANED_IMAGE_BRANCH ends up being an empty string.

 ❮❮❮ DOCKER_REGISTRY=docker IMAGE_BRANCH="a/b" IMAGE_TAG="lol" make build
CLEANED_IMAGE_BRANCH=
DOCKER_BUILDKIT=1 docker build --build-arg GITHUB_ACTOR= --build-arg GITHUB_TOKEN= -t docker/strick:-lol -t docker/strick:-latest .
invalid argument "docker/strick:-lol" for "-t, --tag" flag: invalid reference format
See 'docker build --help'.
make: *** [build] Error 125

What's the correct way to perform string substitution in a makefile script?

CodePudding user response:

You could just use the subst function:

CLEANED_IMAGE_BRANCH=$(subst /,-,$(IMAGE_BRANCH))

If I run this Makefile:

GITHUB_ACTOR=someuser
GITHUB_TOKEN=token
DOCKER_REGISTRY=ghcr.io
IMAGE_BRANCH=feature/a-b-c
IMAGE_TAG=foo

CLEANED_IMAGE_BRANCH=$(subst /,-,$(IMAGE_BRANCH))

build:
    echo DOCKER_BUILDKIT=1 docker build \
            --build-arg GITHUB_ACTOR=${GITHUB_ACTOR} \
            --build-arg GITHUB_TOKEN=${GITHUB_TOKEN} \
            -t ${DOCKER_REGISTRY}/strick:${CLEANED_IMAGE_BRANCH}-${IMAGE_TAG} \
            -t ${DOCKER_REGISTRY}/strick:${CLEANED_IMAGE_BRANCH}-latest .

I get as output:

echo DOCKER_BUILDKIT=1 docker build \
        --build-arg GITHUB_ACTOR=someuser \
        --build-arg GITHUB_TOKEN=token \
        -t ghcr.io/strick:feature-a-b-c-foo \
        -t ghcr.io/strick:feature-a-b-c-latest .
DOCKER_BUILDKIT=1 docker build --build-arg GITHUB_ACTOR=someuser --build-arg GITHUB_TOKEN=token -t ghcr.io/strick:feature-a-b-c-foo -t ghcr.io/strick:feature-a-b-c-latest .

CodePudding user response:

First, when you want to pass a $ to the shell you have to escape it from make, because $ is special to make.

Second, every logical line in the recipe is run in a separate shell so if you want shell variables set in one line to be visible in another line you have to connect them via backslash.

build:
        CLEANED_IMAGE_BRANCH=$$(echo ${IMAGE_BRANCH} | sed 's/\//-/g') \
        DOCKER_BUILDKIT=1 docker build --build-arg GITHUB_ACTOR=${GITHUB_ACTOR} --build-arg GITHUB_TOKEN=${GITHUB_TOKEN} -t ${DOCKER_REGISTRY}/strick:${CLEANED_IMAGE_BRANCH}-${IMAGE_TAG} -t ${DOCKER_REGISTRY}/strick:${CLEANED_IMAGE_BRANCH}-latest .

Of course using make functions is also a fine idea, as long as you're willing to commit (or have already committed) to requiring GNU make.

  • Related