Answers: <p>How it should look like:</p>
  
  <ol>
  <li>Commit changes in some microservice and push it to VCS origin repo</li>
  <li>CI system sees new commit</li>
  <li>CI starts build and tests</li>
  <li>If everything's good, it pushes image to docker registry with tags</li>
  </ol>
  
  <p>So, the answer is: CI should know, what service has changes.</p>
  
Answers: CC BY-SA 4.0
Answers: 2018-09-16T13:31:39.950Z
Answers: Hi @chupasaurus, how CI would know? I would have to make different build scripts for different branches?
Answers: Renato Pereira
Answers: CC BY-SA 4.0
Answers: 2018-09-16T14:02:29.503Z
Answers: @renatogbp CI should have triggers for commits.
Answers: chupasaurus
Answers: CC BY-SA 4.0
Answers: 2018-09-16T14:12:30.057Z
Answers: I know it has triggers, but it will be based on the default job. My solution file includes 4 microservices. If I add a new commit, the job will build the whole solution and publish all 4 images again, even though I had changed only one microservice
Answers: Renato Pereira
Answers: CC BY-SA 4.0
Answers: 2018-09-16T14:16:34.353Z
Answers: Microservices should be independent to each other so you could separate build/deploy pipelines for each one.
Answers: chupasaurus
Answers: CC BY-SA 4.0
Answers: 2018-09-16T14:21:13.347Z
Answers: Hmm, so that means I should have a VCS origin repo for each microservice? And also one repo for the gateway?
Answers: Renato Pereira
Answers: CC BY-SA 4.0
Answers: 2018-09-16T15:02:46.463Z
Answers: It's a most common way. There are companies which use monorepo, but one have to add the script in the build pipeline to detect which projects are changed.
  Dunno what you're calling the "gateway".
Answers: chupasaurus
Answers: CC BY-SA 4.0
Answers: 2018-09-16T16:22:59.727Z
Answers: We have a gateway that does the routing between the clients and the microservices. We use Ocelot with the BFF (backend-for-frontend) approach
Answers: Renato Pereira
Answers: CC BY-SA 4.0
Answers: 2018-09-16T19:44:22.350Z
Answers: You should add a service discovery to cover up the configuration steps. With quick lurking through Ocelot docs, Consul is well supported.
Answers: chupasaurus
Answers: CC BY-SA 4.0
Answers: 2019-01-02T19:42:10.783Z
Answers: One repo per deployable is best and is most widely supported by build tools. Historically source control systems at big companies with “enterprise” (aka broken) processes to get access to the code, or that needed a sysadmin to create a new repo, forced monster (aka mono) repos. Anyone that doesn’t face those historic pains shouldn’t be using a monster repo. The disadvantages of a monster repo are performance, git tags of releases applying to the whole repo not the one service release, having to make custom code to deploy only one service, noisier git log, a noisier issue tracker, ...
Answers: simbo1905
Answers: CC BY-SA 4.0
Answers: 2018-09-16T13:26:16.157Z
Answers: 2018-09-16T13:26:16.157Z
Answers: chupasaurus
Answers: <p>@chupasaurus gave an answer based on a multi-repo solution. </p>
  
  <p>Based on this <a href="https://stackoverflow.com/a/45507614/3223737">answer</a>, 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.</p>
  
  <pre><code>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 &amp;&amp; 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
  }
  </code></pre>
  
  <p>This code isn't fully tested, I just wanted to give a practical approach.</p>
  
Answers: CC BY-SA 4.0
Answers: 2019-01-02T19:42:36.727Z
Answers: does the code work?
Answers: simbo1905
Answers: CC BY-SA 4.0
Answers: 2018-10-03T22:04:31.603Z
Answers: 2018-10-03T22:04:31.603Z
Answers: Renato Pereira
Body: <p>I am starting to use Continuous Integration on my microservices solution (monorepo approach), and I am referencing this <a href="https://devops.stackexchange.com/a/3342/9772">post</a> for versioning approach. </p>
  
  <p>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.</p>
  
  <p>Am I misunderstanding the concept? Sorry, this whole microservices and docker thing are pretty new to me.</p>
  
Comments: CC BY-SA 4.0
Comments: 2018-09-16T06:51:41.987Z
Comments: Hi @renatogpb, welcome to SO. The whole idea behind micro-services is that you could make changes in one of them and deploy just that, without affecting other parts of your infrastructure. Could you please go into more detail about how your CI works ? Which process are you referring to ?
Comments: vishnu narayanan
Comments: CC BY-SA 4.0
Comments: 2018-09-16T12:50:16.923Z
Comments: Hi @vishnunarayanan, thanks! So I didn’t implement the actually CI yet, but I was thinking about doing: checkout repository, build de images using “docker-compose -d —build” (I would set some environment variable to replace {$TAG} of the images, and then “docker push”. So, I know what microservices I made the change, but the CI doesn’t know. That’s why I am building all the images. How can I make the CI know about which one I’ve changed?
Comments: Renato Pereira
Comments: CC BY-SA 4.0
Comments: 2019-01-02T19:16:26.307Z
Comments: Mono repo is a bit of an anti-pattern. As you point out if you make a git tag to release one microservice all of the code has the same tag even if it not deployed in that state. With git it’s more natural to group a system as a organisation and have a repo per deployable (either a service or a library).
Comments: simbo1905
Tags: <docker><containers><microservices>
Title: Automated tag versioning on unchanged docker images
UserDisplayName: Renato Pereira
ThreadText: # Automated tag versioning on unchanged docker images
  
  (Asked by: username_0 on 2018-09-14)
  
  I am starting to use Continuous Integration on my microservices solution (monorepo approach), and I am referencing this [post](https://devops.stackexchange.com/a/3342/9772) 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.
  
  **Tags:** docker, containers, microservices
  
  > **Comments:**
  > **username_1**: Hi @renatogpb, welcome to SO. The whole idea behind micro-services is that you could make changes in one of them and deploy just that, without affecting other parts of your infrastructure. Could you please go into more detail about how your CI works ? Which process are you referring to ?  
  > **username_0**: Hi @username_1, thanks! So I didn’t implement the actually CI yet, but I was thinking about doing: checkout repository, build de images using “docker-compose -d —build” (I would set some environment variable to replace {$TAG} of the images, and then “docker push”. So, I know what microservices I made the change, but the CI doesn’t know. That’s why I am building all the images. How can I make the CI know about which one I’ve changed?  
  > **username_2**: Mono repo is a bit of an anti-pattern. As you point out if you make a git tag to release one microservice all of the code has the same tag even if it not deployed in that state. With git it’s more natural to group a system as a organisation and have a repo per deployable (either a service or a library).  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_3 on 2018-09-16. Score: 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.
  
  > **Comments:**
  > **username_0**: Hi @username_3, how CI would know? I would have to make different build scripts for different branches?  
  > **username_3**: @renatogbp CI should have triggers for commits.  
  > **username_0**: I know it has triggers, but it will be based on the default job. My solution file includes 4 microservices. If I add a new commit, the job will build the whole solution and publish all 4 images again, even though I had changed only one microservice  
  > **username_3**: Microservices should be independent to each other so you could separate build/deploy pipelines for each one.  
  > **username_0**: Hmm, so that means I should have a VCS origin repo for each microservice? And also one repo for the gateway?  
  > **username_3**: It's a most common way. There are companies which use monorepo, but one have to add the script in the build pipeline to detect which projects are changed. Dunno what you're calling the "gateway".  
  > **username_0**: We have a gateway that does the routing between the clients and the microservices. We use Ocelot with the BFF (backend-for-frontend) approach  
  > **username_3**: You should add a service discovery to cover up the configuration steps. With quick lurking through Ocelot docs, Consul is well supported.  
  > **username_2**: One repo per deployable is best and is most widely supported by build tools. Historically source control systems at big companies with “enterprise” (aka broken) processes to get access to the code, or that needed a sysadmin to create a new repo, forced monster (aka mono) repos. Anyone that doesn’t face those historic pains shouldn’t be using a monster repo. The disadvantages of a monster repo are performance, git tags of releases applying to the whole repo not the one service release, having to make custom code to deploy only one service, noisier git log, a noisier issue tracker, ...  
  
  ---
  
  ### Answer by username_0 on 2018-10-03. Score: 0
  
  @username_3 gave an answer based on a multi-repo solution.
  
  Based on this [answer](https://stackoverflow.com/a/45507614/3223737), 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.
  
  > **Comments:**
  > **username_2**: does the code work?  
  
  ---
  
  