I'm trying to use a part of current branch name as a tag for publishing docker image in CI pipeline. The problem is that in my org, there is a convention to name branches like feature/foo, and docker tags can't contain slashes. So I want to split the string on '/' symbol and take the last part.
The full branch name, with slashes, should be in variable github.ref_name. Here is the expression I'm trying to evaluate: ${{ github.ref_name.split('/')[-1] }}.
I get this error: Unable to interpolate expression 'format('{0}', github.ref_name.split('/')[-1])': Failed to parse: unexpected token "(" while parsing arguments of function call. expecting ",", ")"
What are the options for manipulating strings in github actions expression? I didn't find it in docs https://docs.github.com/en/actions/learn-github-actions/expressions
This technique doesn't need to bring in anything from the actions marketplace.
Add this to steps: in an action:
- name: Split branch name
env:
BRANCH: ${{ github.ref_name }}
id: split
run: echo "fragment=${BRANCH##*/}" >> $GITHUB_OUTPUT
It captures the output of a shell command. The only necessary actions are setting github.ref_name to an environmental variable and using parameter expansion to get the part of the branch name you want.
## greedily removes the subsequent pattern off the front*/ matches anything followed by a /##*/ removes everything up to and including the final forward slash.Because id is split, and name=fragment, you then reference your split string with steps.split.outputs.fragment. For example,
# Another step
- name: Test variable
run: |
echo ${{ steps.split.outputs.fragment }}
Other parameter expansion features would be useful here, like #, %, and %% in addition to ##.
Originally I spawned another process with $(echo ${BRANCH##*/}) but that is unnecessary. The variable can be directly referenced.
I'm doing something essentially the same and using an action was the easiest temporary workaround, however I also would have preferred something built-in like a string-splitting expression. For now here is what worked.
- uses: jungwinter/split@master
id: branch
with:
msg: ${{ github.ref_name }}
separator: "/"
maxsplit: -1
From its repo:
Outputs
_0,_1, ...,_n: Each result of a split
- According to metadata syntax of outputs, it has
_prefix- Currently, support only 100 splits
length: Length of the splits
So, then I can reference each portion of the string with steps.branch.outputs._n, with branch being the id and n being the split index.
I was looking for the first instead of the last value in the branch name, so I could set maxsplit to 1 and just take _0. In your case you might need to do some magic with checking length and choosing the index from there.
I ended up using bash to do the split and publishing it as job output. In the retrospect should have went for just installing python (bash syntax is way more confusing and less maintainable).
build-docker:
container: docker:cli
outputs:
docker-tag: ${{steps.docker-tag.outputs.DOCKER_TAG}}
steps:
- name: add bash
run: |
apk update
apk upgrade
apk add bash
- name: determine docker tag by splitting branch name on slash
id: docker-tag
shell: bash
run: |
split=(${GITHUB_REF_NAME//\// })
index=$((${#split[@]}-1))
DOCKER_TAG=${split[$index]}
echo DOCKER_TAG=$DOCKER_TAG >> $GITHUB_ENV
echo "::set-output name=DOCKER_TAG::$DOCKER_TAG"
- name: Build and push
uses: docker/build-push-action@v3
file: ./docker/ci/Dockerfile
push: true
tags: |
artifactory.com/repo/image:${{ env.DOCKER_TAG }}
test-job:
needs: build-docker
runs-on: [self-hosted, Linux, docker]
container:
image: artifactory.com/repo/image:${{ needs.build-docker.outputs.docker-tag }}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With