1

I am starting to use Continuous Integration on my microservices solution (monorepo approach), and I am referencing this post for versioning approach.

But, let's say I make some change in one of the microservice and commit that change, but all the others are exactly the same. How the process would know that those microservices (docker images) weren't changed so don't need to increase the build number? I feel like I would end-up with many docker images with different build numbers but same content.

Am I misunderstanding the concept? Sorry, this whole microservices and docker thing are pretty new to me.

2 Answers2

1

How it should look like:

  1. Commit changes in some microservice and push it to VCS origin repo
  2. CI system sees new commit
  3. CI starts build and tests
  4. If everything's good, it pushes image to docker registry with tags

So, the answer is: CI should know, what service has changes.

chupasaurus
  • 547
  • 3
  • 9
0

@chupasaurus gave an answer based on a multi-repo solution.

Based on this answer, I came up with the following jenkins pipeline approach. I've decided to build and test the whole solution, but you can use the same approach from "Push Image" stage to build and test only the changed services.

pipeline {
agent any
environment {
    CHANGES = getChangeLog()
}
stages {
    stage('Build') {
        steps {
            bat 'dotnet clean solutionFile.sln'
            bat 'dotnet build solutionFile.sln'
        }
    }
    stage('Test') {
        steps {
            bat 'dotnet test solutionFile.sln --no-build --logger:trx;LogFileName=results.trx'
            // parse tests
        }
    }
    stage('Push Image') {
        stage('serviceA') {
            when {
                allOf {
                        expression {
                            hasChanged = powershell(returnStdout: true, script: '"$env:CHANGES" -like "*serviceA*").trim() // check if any file path contains "serviceA"
                            return  hasChanged == "True" 
                        }
                        branch 'master'
                }                        
            }
            steps {   
                // set tag or use latest by default from docker-compose      
                bat 'docker-compose build serviceA.api'
                bat 'docker-compose push registry/serviceA.api'
            }
        }
    }
    stage('Deploy Image') {
        stage('serviceA') {
            // deploy image code
        }
    }
}

def getChangeLog(){
    def changes = ""
    build = currentBuild
    while(build != null && build.result != 'SUCCESS') {
        changes += "In ${build.id}:\n"
        for (changeLog in build.changeSets) {
            for(entry in changeLog.items) {
                for(file in entry.affectedFiles) {
                    changes += "${file.path}\n"
                }
            }
        }
        build = build.previousBuild
    }
    echo changes
    return changes
}

This code isn't fully tested, I just wanted to give a practical approach.