How to retrieve the last tag made on develop and store it properly?

Hello in my config I want to get the last tag created (the last tag is created on develop by a CI step), but I always have an empty value and the echo give me the plain “${GIT_TAG}”.

The part of my script that doing what I search to do:

def GIT_TAG = ''

  stage('checkout') {
    checkout([
      $class: 'GitSCM',
      branches: [[name: '*/staging']],
      userRemoteConfigs: [[url: 'git@github.com:xxxxx.git', credentialsId: 'jenkins-ssh-xxxx']]
    ])
  }

  stage('get last tag') {
    GIT_TAG = sh(returnStdout: true, script: "git tag --sort version:refname | tail -1").trim()
    echo 'Latest Git tag: ${GIT_TAG}'
  }

The echo give:

Latest Git tag: ${GIT_TAG}

I also have defined the GIT_TAG env in the config of Jenkins with a default value, and now I get this default value, don’t know if it’s a good idea to set an env in jenkins too:

docker buildx build --platform linux/x86_64 --rm --no-cache . -t xxxx:latest --build-arg GIT_TAG=no_tag

FYI (I know this is different) in my console I get the tag:

xxxx on  feat/improve-ci-step [!?] via  v22.14.0 
❯ git tag --sort version:refname | tail -1   
v1.0.0

'single quote' text always remains a plain old String, "double quote" text becomes a GString if it contains the ${interpolations}, and performs the values substitution. See The Apache Groovy programming language - Syntax

 def x = 123 
 def s1 = 'string ${x}' 
 def s2 = "string" 
 def g = "gstring ${x}" 
 println(s1) 
 println(s1.getClass()) 
 println(s2) 
 println(s2.getClass()) 
 println(g) 
 println(g.getClass()) 

string ${x}
class java.lang.String
string
class java.lang.String
gstring 123
class org.codehaus.groovy.runtime.GStringImpl

upd: So just to be clear; from what I see, you already store the output of sh() properly, it’s just the echo() call that is slightly wrong :slight_smile:

2 Likes

OMG :sweat_smile: Thanks for that !

Now the echo work pretty well, but my build image step is still empty :confused:

I remove the env from Jenkins config btw.

echo "Latest Git tag: ${GIT_TAG}" >> Latest Git tag: V1.0.0
--build-arg GIT_TAG=${GIT_TAG}' >> --build-arg GIT_TAG=
#!groovy

node {

  def GIT_TAG = ""

  stage('checkout') {
    checkout([
      $class: 'GitSCM',
      branches: [[name: '*/staging']],
      userRemoteConfigs: [[url: 'git@github.com:xxx.git', credentialsId: 'jenkins-ssh-xxx']]
    ])
  }

  stage('get last tag') {
    GIT_TAG = sh(returnStdout: true, script: "git tag --sort version:refname | tail -1").trim()
    echo "Latest Git tag: ${GIT_TAG}"
  }

  stage('build image') {
    sh 'cp .env.staging .env.production'
    sh 'aws ecr get-login-password --region xxx | docker login --username xxx --password-stdin xxx'
    sh 'docker buildx build --platform linux/x86_64 --rm --no-cache . -t xxx:latest --build-arg GIT_TAG=${GIT_TAG}'
    sh 'docker tag xxx:latest xxx:latest'
  }

  stage('push image') {
    sh 'docker push xxx:latest'
  }

  stage('deploy') {...}
}

That’s a slightly different manifestation of the same problem you. Single quotes → ${} is not evaluated → string is passed to the script as is. So you literally get a script file like

#!/bin/sh
docker buildx build --platform linux/x86_64 --rm --no-cache . -t xxx:latest --build-arg GIT_TAG=${GIT_TAG}

that gets executed via sh -ex /jenkins/workspace/jobname@tmp/script.sh.
Groovy variables do not automatically translate into environment variables that a shell process would see (withEnv() and withCredentials() do that). So from shell’s perspective GIT_TAG does not exist – and a variable that does not exist when referenced in shell evaluates into an empty string.

Same fix as before: replace '' with "" for anything where you want the Groovy to do the substitution.

2 Likes

I suspected it when I posted the answer :sweat_smile:
Thanks a lot !