Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

github action expressions - split string

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

like image 563
Boschie Avatar asked Dec 07 '25 06:12

Boschie


2 Answers

IMPROVED:

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 /
  • So, ##*/ 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 ##.

220829: Final update

Originally I spawned another process with $(echo ${BRANCH##*/}) but that is unnecessary. The variable can be directly referenced.


ORIGINAL:

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.

like image 163
kees Avatar answered Dec 09 '25 23:12

kees


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 }}
      
like image 24
Boschie Avatar answered Dec 09 '25 23:12

Boschie