jenkinsjenkins-pipeline

How to run a top-level shell script in a Git submodule inside a Jenkins pipeline?


I have a Git submodule, and have a delete-branches.sh script at the top level. I'm able to do this on my terminal

$ git submodule foreach 'cp ../delete-branches.sh . && ./delete-branches.sh true && rm -f ./delete-branches.sh'

which executes the script as expected. However when I put this in a Jenkins pipeline, like this. DRY_RUN is a job parameter.

    stage('Delete branches') {
        sshagent(credentials: ['bitbucket-creds']) {
            sh(label: "Delete branches",
               script: "git submodule foreach \'cp ../delete-branches.sh . && ./delete-branches.sh ${env.DRY_RUN}\'",
               returnStatus: true)
        }
    }

I get

git submodule foreach cp ../delete-branches.sh . && ./delete-branches.sh true
Entering 'module1'
./delete-branches.sh: 6: [[: not found
./delete-branches.sh: 6: [[: not found
fatal: option '--since' must come before non-option arguments
./delete-branches.sh: 6: [[: not found
./delete-branches.sh: 6: [[: not found
./delete-branches.sh: 6: [[: not found
fatal: option '--since' must come before non-option arguments

Here's the script, which I got from this post:

#!/bin/sh

DRY_RUN=$1
ECHO='echo '
for branch in $(git branch -a | sed 's/^\s*//' | sed 's/^remotes\///' | grep -v 'master$' | grep -v 'v2$'); do
  if ! ( [[ -f "$branch" ]] || [[ -d "$branch" ]] ) && [[ "$(git log $branch --since "1 year ago" | wc -l)" -eq 0 ]]; then
    if [[ "$DRY_RUN" = "false" ]]; then
      ECHO=""
    fi
    local_branch_name=$(echo "$branch" | sed 's/remotes\/origin\///')
    $ECHO git branch -d "${local_branch_name}"
    $ECHO git push origin --delete "${local_branch_name}"
  fi
done

The script has executable permissions. What's the correct syntax for running the script in the pipeline?


Solution

  • Try setting shell in jenkins:

    Manage Jenkins > Configure System > Shell > Shell executable and set your shell path (ie /bin/bash or sh)

    Your script example starts with

    #!/bin/sh
    

    The other option is modify your script to run with bash, keeping jenkins without changes

    #!/bin/bash
    
    DRY_RUN=$1
    ECHO='echo '
    
    # Loop over all remote branches except 'master' and 'v2'
    for branch in $(git branch -a | sed 's/^[[:space:]]*//' | sed 's/^remotes\///' | grep -v 'master$' | grep -v 'v2$'); do
      # Check if there's no file or directory with the branch name and the branch has no commits in the last year
      if [[ ! -f "$branch" && ! -d "$branch" && "$(git log "$branch" --since "1 year ago" | wc -l)" -eq 0 ]]; then
        if [[ "$DRY_RUN" == "false" ]]; then
          ECHO=""
        fi
        local_branch_name=$(echo "$branch" | sed 's/^origin\///')
        $ECHO git branch -d "$local_branch_name"
        $ECHO git push origin --delete "$local_branch_name"
      fi
    done