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.