How to start from a clean stage after maven release job fails in GitLab pipeline?

32 views Asked by At

I am implementing maven release process on my gitlab ci cd pipeline. After the release is completed it should push the docker image with the name of the tag release process created. It should then be deployed to internal cloud and to artifactory. I have the following problem. When there is an error during maven release job, and it fails; lets say one of the CI/CD variables was missing and the job fails because of it. The mvn release:prepare already creates the tag and commit the changes in pom files, and when it comes to mvn release:perform, it faces an error to push the images. So when I fix the missing variable problem, and re run the job, it fails from the beginning, saying "Updates were rejected because the tip of your current branch is behind" because it already commited the files in the previous stages, but not pushed.

How can i make sure, when a problem occurs during the maven release job and I want to re run it, I start from clean stage, reverting the previous commits and all the changes?

I tried to perform rollback operation but it wasnt successful as well

gitlab-ci.yml :

stages:
  - build
  - test
  - release
  - push
  - deploy
  - rollback

cache:
  key: $CI_JOB_NAME
  paths:
    - /.m2/repository

gemnasium-maven-dependency_scanning:
  stage: test
  variables:
    MAVEN_CLI_OPTS: "-DskipTests --batch-mode"
    DS_MAX_DEPTH: -1

.setup-mvn:
  before_script:
    - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
    - eval $(ssh-agent -s)
    - chmod 400 "$SSH_PRIVATE_KEY"
    - ssh-add "$SSH_PRIVATE_KEY"
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - git config --global user.email "[email protected]"
    - git config --global user.name " GitLab CI/CD"
    - ssh-keyscan -p 2222 code.gitlab.com >> ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts
    - mkdir -p ~/.m2
    - |
      cat <<EOF > ~/.m2/settings.xml
      <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
      ....
      EOF


build:
  image: docker-local.artifactory.com/maven:3.9.6-eclipse-temurin-21-jammy
  variables:
    KUBERNETES_CPU_REQUEST: "3"
    KUBERNETES_CPU_LIMIT: "5"
    KUBERNETES_MEMORY_REQUEST: "4Gi"
    KUBERNETES_MEMORY_LIMIT: "7Gi"
  stage: build
  extends: .setup-mvn
  script:
    - mvn clean package
  artifacts:
    paths:
      - server/target/*.jar


maven_release:
  stage: release
  image: docker-local.artifactory.com/maven:3.9.6-eclipse-temurin-21-jammy-openssh
  extends: .setup-mvn
  when: manual
  script:
    - git checkout -B "$CI_COMMIT_REF_NAME"
    - mvn release:clean release:prepare --batch-mode -DscmCommentPrefix="[skip ci]"
    - mvn release:perform -Dgoals=install

push_image:
  stage: push
  dependencies:
    - maven_release
  image:
    name: docker-local.artifactory.com/executor:v1.14.0-debug
    entrypoint: [""]
  when: manual
  script:
    - VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
    - mkdir -p /kaniko/.docker
    - echo $DOCKER_AUTH_CONFIG > /kaniko/.docker/config.json
    - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile ./Dockerfile --destination docker-local.artifactory.com/$CI_PROJECT_NAME:$VERSION
    - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile ./Dockerfile --destination docker-local.artifactory.com/$CI_PROJECT_NAME:latest
    - echo "Docker image pushed."

pom.xml (for maven-release-plugin only) :

<build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-release-plugin</artifactId>
                <version>3.0.1</version>
                <configuration>
                    <pushChanges>false</pushChanges>
                    <projectVersionPolicyId>SemVerVersionPolicy</projectVersionPolicyId>
                    <tagNameFormat>v-@{project.version}</tagNameFormat>
                </configuration>
            </plugin>
        </plugins>
    </build>
1

There are 1 answers

0
Mustafa Güler On

You can add another stage to reset if there is an error on mvn release:perform -Dgoals=install || exit 1 command. So you don't have to control anything because repo will be cleaned if there is an error.

stages:
  - build
  - test
  - release
  - push
  - deploy
  - rollback

cache:
  key: $CI_JOB_NAME
  paths:
    - /.m2/repository

gemnasium-maven-dependency_scanning:
  stage: test
  variables:
    MAVEN_CLI_OPTS: "-DskipTests --batch-mode"
    DS_MAX_DEPTH: -1

.setup-mvn:
  before_script:
    - 'command -v ssh-agent >/dev/null || ( apt-get update -y && apt-get install openssh-client -y )'
    - eval $(ssh-agent -s)
    - chmod 400 "$SSH_PRIVATE_KEY"
    - ssh-add "$SSH_PRIVATE_KEY"
    - mkdir -p ~/.ssh
    - chmod 700 ~/.ssh
    - git config --global user.email "[email protected]"
    - git config --global user.name " GitLab CI/CD"
    - ssh-keyscan -p 2222 code.gitlab.com >> ~/.ssh/known_hosts
    - chmod 644 ~/.ssh/known_hosts
    - mkdir -p ~/.m2
    - |
      cat <<EOF > ~/.m2/settings.xml
      <settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
      ....
      EOF

rollback_release:
  stage: rollback
  extends: .setup-mvn
  script:
    - git reset --hard HEAD~1
    - git push -f origin $CI_COMMIT_REF_NAME

build:
  image: docker-local.artifactory.com/maven:3.9.6-eclipse-temurin-21-jammy
  variables:
    KUBERNETES_CPU_REQUEST: "3"
    KUBERNETES_CPU_LIMIT: "5"
    KUBERNETES_MEMORY_REQUEST: "4Gi"
    KUBERNETES_MEMORY_LIMIT: "7Gi"
  stage: build
  extends: .setup-mvn
  script:
    - mvn clean package
  artifacts:
    paths:
      - server/target/*.jar

maven_release:
  stage: release
  image: docker-local.artifactory.com/maven:3.9.6-eclipse-temurin-21-jammy-openssh
  extends: .setup-mvn
  when: manual
  script:
    - git checkout -B "$CI_COMMIT_REF_NAME"
    - mvn release:clean release:prepare --batch-mode -DscmCommentPrefix="[skip ci]"
    - mvn release:perform -Dgoals=install || exit 1

push_image:
  stage: push
  dependencies:
    - maven_release
  image:
    name: docker-local.artifactory.com/executor:v1.14.0-debug
    entrypoint: [""]
  when: manual
  script:
    - VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)
    - mkdir -p /kaniko/.docker
    - echo $DOCKER_AUTH_CONFIG > /kaniko/.docker/config.json
    - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile ./Dockerfile --destination docker-local.artifactory.com/$CI_PROJECT_NAME:$VERSION
    - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile ./Dockerfile --destination docker-local.artifactory.com/$CI_PROJECT_NAME:latest
    - echo "Docker image pushed."