Replies: 9 comments 6 replies
-
My solution to this problem was to provide an override parameter to the pipeline which can be manually set forcing the generation of a new Docker image ? See here for code |
Beta Was this translation helpful? Give feedback.
-
@JehandadKhan Thank you for the code. That is indeed a simple workaround to build docker image during the branch development. I'll borrow it to get my PR #1673 done first. |
Beta Was this translation helpful? Give feedback.
-
@junliume Please add @pfultz2 to this discussion. Also I recommend labeling with |
Beta Was this translation helpful? Give feedback.
-
@zhanglx13 I highly recommend removing all the mentions of |
Beta Was this translation helpful? Give feedback.
-
The idea of reusing docker images from the "parent" branches is good but it's generic implementation seems too complex. Why docker build caching is not effective anymore? I remember it worked well some time ago. |
Beta Was this translation helpful? Give feedback.
-
[Informative] @zhanglx13 Thank you very much for the detailed analysis 👍 ! |
Beta Was this translation helpful? Give feedback.
-
@atamazov It seems to me that other branches are merging into the |
Beta Was this translation helpful? Give feedback.
-
I dont see the reason to reinvent the wheel. Why not just use Alternatively, you could always build the docker files on the same machine so you can reuse the local build cache. Then tag the docker image with the commit hash and push the image to dockerhub/artifactory. Then each job would pull the docker image tag with its commit hash. The local docker layer caches will help speed up the push and pull of docker images. There is no need to track branch names or changes against |
Beta Was this translation helpful? Give feedback.
-
Proposal of the process of updating the CI docker image + discussion: #1897 (comment) |
Beta Was this translation helpful? Give feedback.
-
Problem
The current logic to rebuild the docker image is when a new branch is pushed. This has the following two drawbacks:
Proposal
The docker image should be rebuild if and only if some dependencies or the
Dockerfile
itself are changed. Here is the general idea of the proposal:git rev-parse --short HEAD
) in the tag of the image. Therefore, the name of each image should has the form:${MIOPEN_IMAGE_URL}:miopen_ci_${branchname}_${commitID}_[usr|opt]
HEAD
to see if there is a change in the dependencies orDockerfile
.HEAD
as the commit id in the tag.develop
branch can only fall into this case since Jenkins should always have images built for thedevelop
branch.develop
branch) has not changed any dependencies or theDockerfile
before. Then Jenkins comparesHEAD
with the fork point between this branch and thedevelop
branch to see if there is a change in the dependencies of theDockerfile
.HEAD
as the commit id in the tag.develop
branch. Note that the commit id of this image is the same or later than the fork point. In this way, the new branch will always be tested with the latest dependencies installed in the image.Benefits
The effect of the proposed mechanism is a great drop of the number of rebuilds. The docker image is rebuilt if and only if some dependency requirements are changes with one exception mentioned in Case 5.1.
Demos
Here are some scenarios to illustrate the proposed image building mechanism.
In the above diagram,
O
stands for a commit on thedevelop
branch andX
for commits on a new branchmybranch
.F
is the fork point between the two branches.Assume I first pushed
mybranch
whenP
is theHEAD
. Then I added two commits and pushed again whenQ
is theHEAD
.Case 1: no dependency change in
mybranch
Since I am not changing anything about the dependencies, there is no need to build a new image for
mybranch
. And since no images are built formybranch
, both pushes fall into the scenario of 2.ii.b, i.e. neithergit diff P..F
norgit diff Q..F
contains dependency changes. And in this case, the image used formybranch
is the latest built image for thedevelop
branch. Then we have two sub-cases:${MIOPEN_IMAGE_URL}:miopen_ci_develop_[A|F]_[usr|opt]
In this case, the dependency requirements have not changed since
A
orF
. Therefore, it makes sense forP
andQ
to used to same image asA
orF
.${MIOPEN_IMAGE_URL}:miopen_ci_develop_B_[usr|opt]
In this case, some dependency requirements have changed by another PR, which have been merged into the
develop
branch before my push ofmybranch
. It makes sense formybranch
to be tested with the latest dependency requirements to catch bugs as early as possible (at least beforemybranch
is merged).Case 2: dependency changes in my first push but no more changes in my second push
When I first push
mybranch
with headP
, Jenkins finds that the difference betweenF
andP
contains dependency changes. Therefore, it rebuilds the image with tagmiopen_ci_mybranch_P_[usr|opt]
as in 2.ii.a.At this moment, the image tag for the
develop
branch can point toA
,F
, orB
. In the case ofA
orF
,mybranch
has a newer version of the dependency requirements. However, in the case ofB
, the newer version of the dependency requirements could be on thedevelop
branch. In this case,mybranch
is tested with its local change to the dependency requirements. The local change could be tested again whenmybranch
is merged into thedevelop
branch.The second push of
mybranch
with headQ
does not have more changes to the dependency requirements compared toP
. Therefore, Jenkins will use the previously built image with tagmiopen_ci_mybranch_P_[usr|opt]
as indicated in 2.i.b.Case 3: no dependency change in my first push but some are in my second push
The first push (with head
P
) falls into 2.ii.b, in which case the latest built image for thedevelop
branch is used.For the second push with head
Q
, Jenkins still cannot find an image with a tag that includemybranch
. However, since the second push includes changes to the dependency requirements, the image is rebuilt with a new tagmiopen_ci_mybranch_Q_[usr|opt]
as indicated in 2.ii.a. Note that Jenkins comparesQ
withF
to make the decision sinceP
andF
are equivalent in terms of dependency requirements. And sincemybranch
has local changes to the dependency requirements, those on thedevelop
branch are ignored when testingmybranch
.Case 4: dependency changes in my first push and more dependency changes in my second push
The first push falls into 2.ii.a since this is the first time
mybranch
is pushed and the image is rebuilt with tagmiopen_ci_mybranch_P_[usr|opt]
.The second push falls into 2.i.a, in which case Jenkins rebuild the image again with a new tag
miopen_ci_mybranch_Q_[usr|opt]
.Case 5: What happens when
mybranch
is mergedIn the above diagram,
M
is the merge point. The image is rebuilt for thedevelop
branch in the following cases:mybranch
has changes but no changes afterF
on thedevelop
branchThis case implies that the last built image for the
develop
branch has a tag pointing toA
orF
, but cannot toB
. For thedevelop
branch,M
contains the dependency requirements changes that is not found inF
orA
. Therefore, the image is rebuilt with tagmiopen_ci_develop_M_[usr|opt]
as indicated in 2.i.a.Note that this image is duplicate to the latest image built for
mybranch
. The proposed mechanism cannot eliminate such duplicates.mybranch
has changes and some commits (sayB
) afterF
on thedevelop
branch have changesIn this case, the merge must have resolved any conflicts of dependency requirements. And Jenkins will trigger a rebuild if and only if
mybranch
has changes that are not covered inB
, i.e.M
is different fromB
in terms of dependency requirements. And the image is rebuilt according to 2.i.a.When
mybranch
does not have dependency requirements changes, no rebuild will happen whenmybranch
is merged into thedevelop
branch sinceM
must be the same asB
orF
orA
in terms of dependency requirements. And this falls into 2.i.b.Beta Was this translation helpful? Give feedback.
All reactions