1

I encountered a problem about GitlabCI and I was hoping someone could help me with that.

The thing is, I want to run a shell script that compare the source branch & target branch in GitlabCI runner when the job is triggered. The .gitlab-ci.yml will look like this.

testJob: // the name of the CI/CD job
  only:
    refs:
      - merge_requests
    change:
      - a/json/folder/*
    before_script:
      ... // some action
    script:
      - bash ./xxx.sh

This job will be triggered if this is a merge request and if there's any changes in the folder that holds a bunch of json files. And then, it will run the shell script.

Inside the shell script, I was going to compare the source and target branch to get the list of modified json files, so I run this command in the shell script.

current_branch=`git rev-parse --abbrev-ref HEAD` // to get the current branch name, i.e. the source branch
diff_message=`git diff --name-only --diff-filter=AM origin/develop..origin/$CI_COMMIT_REF_NAME`

The target branch will be fixed to develop for some reasons. This piece of code works just fine on local but crashes on the GitlabCI runner. So I went to Gitlab to see what's going on and I saw the error message as follows.

fatal: ambiguous argument 'origin/develop..origin/fix/json': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'

My friend told me that the runner will only load the current branch (the source branch of merge request) but not the target branch (develop, in this case). Is it true? If it is true, how am I to get GitlabCI runner to load it. And if it's not possible, is there any alternative for me to get the list of modified json files between two branches?

Thank you.

1 Answers1

0

You can get the target branch through CI_MERGE_REQUEST_TARGET_BRANCH_NAME environment variable and you can change your above example to fetch this branch in the before_script step:

testJob: // the name of the CI/CD job
  before_script:
    - git fetch origin "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"      

It seems that the initial clone uses the same branch name as your target and after this you will have two branches locally that share the same name. I haven't found this causing any problems, but my tests are somewhat limited. Here is an example output when my target branch is main:

 * branch            main       -> FETCH_HEAD
 * [new branch]      main       -> origin/main

To get list of commits added on your target branch, you can run git log HEAD --not "origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" --pretty=format:"%h %s"). Note the added origin/ before target branch name. Otherwise it won't work, because locally you have two branches with the same name as I pointed out earlier. I was expecting that you could use $CI_MERGE_REQUEST_TARGET_BRANCH_SHA instead of the branch name, but in my experiments, this variable was always empty and using it did not work.

As a full example, here is a job that checks for unfinished work in the merge request:

check_unfinished_work:
  stage: test
  before_script:
    - git fetch origin "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
  script:
    - |
      case "$CI_MERGE_REQUEST_TITLE" in wip*|WIP*|dnm*|DNM*)
        printf "\033[31mWork-in-Progress merge request\033[m" >&2
        exit 1
        ;;
      esac
    - |
      while IFS= read -r commit; do
        commit_hash=$(echo "$commit" | cut -d ' ' -f 1)
        commit_subject=$(echo "$commit" | cut -d ' ' -f 2-)
        case "$commit_subject" in
          fixup*)
            printf "\033[31mFound fixup commit '%s'\033[m" "$commit_hash" >&2
            exit 1
            ;;
          squash*)
            printf "\033[31mFound squash commit '%s'\033[m" "$commit_hash" >&2
            exit 1
            ;;
          wip*|WIP*)
            printf "\033[31mFound WIP commit '%s'\033[m" "$commit_hash" >&2
            exit 1
            ;;
          dnm*|DNM*)
            printf "\033[31mFound DNM commit '%s'\033[m" "$commit_hash" >&2
            exit 1
            ;;
        esac
      done <<EOF
      $(git log HEAD --not "origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" --pretty=format:"%h %s")
      EOF
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
mikoni
  • 449
  • 5
  • 6