From 3f7e1c60a5f0b8ae3f720dc016c6302d14cf7509 Mon Sep 17 00:00:00 2001 From: memsharded Date: Thu, 25 Feb 2021 15:47:50 +0100 Subject: [PATCH 1/6] lock bundle --- versioning/lockfiles.rst | 1 + versioning/lockfiles/bundle.rst | 195 +++++++++++++++++++++ versioning/lockfiles/conan_lock_bundle.png | Bin 0 -> 40933 bytes 3 files changed, 196 insertions(+) create mode 100644 versioning/lockfiles/bundle.rst create mode 100644 versioning/lockfiles/conan_lock_bundle.png diff --git a/versioning/lockfiles.rst b/versioning/lockfiles.rst index a865b832861..e57b769e43a 100644 --- a/versioning/lockfiles.rst +++ b/versioning/lockfiles.rst @@ -22,4 +22,5 @@ version ranges or using package revisions. lockfiles/configurations lockfiles/evolving lockfiles/build_order + lockfiles/bundle lockfiles/ci \ No newline at end of file diff --git a/versioning/lockfiles/bundle.rst b/versioning/lockfiles/bundle.rst new file mode 100644 index 00000000000..0fac6b4b07d --- /dev/null +++ b/versioning/lockfiles/bundle.rst @@ -0,0 +1,195 @@ +.. _versioning_lockfiles_bundle: + +Lockfile bundles +================ + +.. warning:: + + This is an **experimental** feature subject to breaking changes in future releases. + + +Every package build using lockfiles requires a given configuration specific lockfile, and after the build, that lockfile is +updated to included the built package revision. If we have different configurations for different variants as different architectures, +compiler versions or Debug/Release, a build will be typically necessary for each one. + +In real life, it is also likely that we might want to build together different applications or products, that could be even disconnected, +and we want to do it as efficiently and fast (in parallel) as possible. We could have the following situation: + + +.. image:: conan_lock_bundle.png + :height: 200 px + :width: 400 px + :align: center + + +In this diagram we see that we are building and releasing 2 different products in our team: ``app1/1.1`` and +``app2/2.3``. ``app1`` depends on ``pkgb/0.1`` (ommiting ``user/channel`` for brevity, but please use it) and +``app2`` depends on ``pkgb/0.2``. In turn, both versions of ``pkgb`` depend on the same ``pkga/0.1`` version. + +If we are building both products for 2 different configurations each (lets say Windows and Linux), we could capture 4 +different lockfiles: + +.. code:: bash + + $ conan lock create --ref=app1/1.1 --base --lockfile-out=app1_base.lock + $ conan lock create --ref=app2/2.3 --base --lockfile-out=app2_base.lock + + $ conan lock create --ref=app1/1.1 -s os=Windows --lockfile=app1_base.lock --lockfile-out=app1_windows.lock + $ conan lock create --ref=app1/1.1 -s os=Linux --lockfile=app1_base.lock --lockfile-out=app1_linux.lock + $ conan lock create --ref=app2/2.3 -s os=Windows --lockfile=app2_base.lock --lockfile-out=app2_windows.lock + $ conan lock create --ref=app2/2.3 -s os=Linux --lockfile=app2_base.lock --lockfile-out=app2_linux.lock + +If we launched these 4 lockfiles builds in parallel, we can see that ``pkga/0.1`` will be built 4 times, 2 times +in Windows and 2 times in Linux. The extra build in each OS is redundant and can be avoided. But we need a way +to orchestrate it, that is what a lockfile bundle is for. + + +Creating a lockfile bundle +-------------------------- + +Creating a lockfile bundle can be done with the ``conan lock bundle create`` command, passing the list of all lockfiles +for all configurations and products, and obtaining one single output bundle: + +.. code:: bash + + $ conan lock bundle create app1_windows.lock app1_linux.lock app2_windows.lock app2_linux.lock --bundle-out=lock.bundle + + +Inspecting the resulting lockfile bundle file, we can see it is a json file with the following structure: + +.. code:: json + + "lock_bundle": { + "app1/1.1@#584778f98ba1d0eb7c80a5ae1fe12fe2": { + "package_id": { + "3bcd6800847f779e0883ee91b411aad9ddd8e83c": { + "lockfiles": { + "app1_windows.lock": [ + "1" + ] + }, + "prev": null, + "modified": null + }, + "60fbb0a22359b4888f7ecad69bcdfcd6e70e2784": { + "lockfiles": { + "app1_linux.lock": [ + "1" + ] + }, + "prev": null, + "modified": null + } + }, + "requires": [ + "pkgb/0.1@#cd8f22d6f264f65398d8c534046e8e20" + ] + }, + +The bundle groups items per "recipe reference", include the recipe revision, like ``app1/0.1@#584778f98ba1d0eb7c80a5ae1fe12fe2``. +For each one, it will list all different binaries, identified by their ``package_id`` that are involved in the different +lockfiles, listing all lockfiles for each ``package_id``. In this case, as ``app1`` only belongs to app1 lockfiles, only +one lockfile ``app1_windows.lock``, ``app1_linux.lock`` is in each ``package_id``. Also the package revision ``prev`` is listed, +in this case being null, because there is no locked binary in the lockfiles, but is going to be built. + +.. note:: + + The relative path between the bundle file and the lockfile files need to be maintained. In the example + ``app1_linux.lock`` means that the lockfile is located in the same folder as the bundle file itself. If + moving the bundle to a different machine, the lockfiles should be moved too, maintaining the same relative + layout. + +The interesting part is in the ``pkga/0.1`` information in the bundle: + +.. code:: json + + "pkga/0.1@#f096d7d54098b7ad7012f9435d9c33f3": { + "package_id": { + "3475bd55b91ae904ac96fde0f106a136ab951a5e": { + "lockfiles": { + "app1_windows.lock": [ + "3" + ], + "app2_windows.lock": [ + "3" + ] + }, + "prev": null, + "modified": null + }, + +Now we can see that for one ``package_id`` there are actually 2 different lockfiles that require it. Both ``app1`` and ``app2`` +depend in this case on ``pkga/0.1``. +This is the information that can be used to avoid duplicated builds. + + + +Using a lockfile bundle to build +-------------------------------- + +The lockfile bundles also can compute a "build order" over the bundle, that will give an ordered list of lists of the +package references that need to be built. In our case we could do: + +.. code:: bash + + $ conan lock bundle build-order lock.bundle --json=build_order.json + [ + ["pkga/0.1@#f096d7d54098b7ad7012f9435d9c33f3"], + ["pkgb/0.1@#cd8f22d6f264f65398d8c534046e8e20", "pkgb/0.2@#cd8f22d6f264f65398d8c534046e8e20"], + ["app1/0.1@#584778f98ba1d0eb7c80a5ae1fe12fe2", "app2/0.1@#3850895c1eac8223c43c71d525348019"] + ] + +The result is a list of lists. Every inner list is a "level", it is formed by mutually independent references that +can be built in parallel, because they don't depend on each other. But every level will have dependencies to the +previous levels, so it is necessary to build those levels in order. + +The build order list can be iterated, building the packages in order. The necessary information is in the bundle +file itself, so we can read it and use it, something like: + + +.. code:: python + + # Get the build order + build_order = json.loads(open("build_order.json").read()) + + # Read the bundle + bundle = json.loads(open("lock.bundle").read()) + bundle = bundle["lock_bundle"] + for level in build_order: # iterate the build_order + for ref in level: # All refs in this level could be built in parallel + # Now get the package_ids and lockfile information + package_ids = bundle[ref]["package_id"] + for pkg_id, info in package_ids.items(): + lockfiles = info["lockfiles"] + lockfile = next(iter(sorted(lockfiles))) # Get the first one, all should be valid to build same packag_id + + os.system("conan install {ref} --build={ref} --lockfile={lockfile} " + "--lockfile-out={lockfile}".format(ref=ref, lockfile=lockfile)) + os.system("conan lock bundle update lock.bundle") + + +This works under the hypothesis that the same binary, identified by the same ``package_id`` will be obtained irrespective +of which lockfile or final product is used to build it. If this doesn't hold true, then the ``package_id`` policies should +be revised until this condition is met. + +.. important:: + + Recall that this is an orchestration mechanism, that can be used to distribute the actual ``conan install`` tasks + to different agents, based on the lockfile itself, we might need some logic to send that build to one or another + build server. If we didn't want to orchestrate and everything can be built in this machine a + ``conan install app1/1.1@ --lockfile={lockfile} --build=missing`` would build all the necessary dependencies in the + graph, in the current agent. + + +Note that the builds themselves are using regular lockfiles. The bundle does not contain the necessary information to +reproduce the dependency graph that is needed to create packages. + +The command ``conan lock bundle update lock.bundle`` manages to update all the connected lockfiles after a reference has been +built. When the build is fired, it is done using 1 of the lockfiles, for a given configuration. That lockfile will get the +updated package revision and status. The ``conan lock bundle update`` does this process in 2 steps: + +- Scan all connected lockfiles for every ``ref`` recipe reference and ``package_id``, and collect those that have been modified. +- Propagate the modified information to all the other connected lockfiles. + +After ``conan lock bundle update``, all packages sharing the same reference and ``package_id`` should have the same status (marked +"modified" and same package revision) diff --git a/versioning/lockfiles/conan_lock_bundle.png b/versioning/lockfiles/conan_lock_bundle.png new file mode 100644 index 0000000000000000000000000000000000000000..829c1dfbf83bd25916752606f535ff580e497d7e GIT binary patch literal 40933 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 ss-l1Sf}r%PZn>e_|DSSYR;N^{SSpWb4 literal 0 HcmV?d00001 From 69cd45e1094c6c4bbf29ca8ed97bd7ea424562b7 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 25 Feb 2021 16:27:08 +0100 Subject: [PATCH 2/6] Update versioning/lockfiles/bundle.rst Co-authored-by: Carlos Zoido --- versioning/lockfiles/bundle.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/versioning/lockfiles/bundle.rst b/versioning/lockfiles/bundle.rst index 0fac6b4b07d..8113d0ae31a 100644 --- a/versioning/lockfiles/bundle.rst +++ b/versioning/lockfiles/bundle.rst @@ -8,8 +8,8 @@ Lockfile bundles This is an **experimental** feature subject to breaking changes in future releases. -Every package build using lockfiles requires a given configuration specific lockfile, and after the build, that lockfile is -updated to included the built package revision. If we have different configurations for different variants as different architectures, +Every package build using lockfiles requires a given configuration-specific lockfile, and after the build, that lockfile is +updated to include the built package revision. If we have different configurations for different variants as different architectures, compiler versions or Debug/Release, a build will be typically necessary for each one. In real life, it is also likely that we might want to build together different applications or products, that could be even disconnected, From b27229856b26c197129fa7eb11826e93ea8cf9f1 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 25 Feb 2021 16:27:16 +0100 Subject: [PATCH 3/6] Update versioning/lockfiles/bundle.rst Co-authored-by: Carlos Zoido --- versioning/lockfiles/bundle.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versioning/lockfiles/bundle.rst b/versioning/lockfiles/bundle.rst index 8113d0ae31a..de5363c8b3b 100644 --- a/versioning/lockfiles/bundle.rst +++ b/versioning/lockfiles/bundle.rst @@ -23,7 +23,7 @@ and we want to do it as efficiently and fast (in parallel) as possible. We could In this diagram we see that we are building and releasing 2 different products in our team: ``app1/1.1`` and -``app2/2.3``. ``app1`` depends on ``pkgb/0.1`` (ommiting ``user/channel`` for brevity, but please use it) and +``app2/2.3``. ``app1`` depends on ``pkgb/0.1`` (omitting ``user/channel`` for brevity, but please use it) and ``app2`` depends on ``pkgb/0.2``. In turn, both versions of ``pkgb`` depend on the same ``pkga/0.1`` version. If we are building both products for 2 different configurations each (lets say Windows and Linux), we could capture 4 From 2b896be923b5e2eddd7047f5ce6c52d353d0c2a0 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 25 Feb 2021 16:27:39 +0100 Subject: [PATCH 4/6] Update versioning/lockfiles/bundle.rst Co-authored-by: Carlos Zoido --- versioning/lockfiles/bundle.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versioning/lockfiles/bundle.rst b/versioning/lockfiles/bundle.rst index de5363c8b3b..d88f7d39841 100644 --- a/versioning/lockfiles/bundle.rst +++ b/versioning/lockfiles/bundle.rst @@ -89,7 +89,7 @@ Inspecting the resulting lockfile bundle file, we can see it is a json file with The bundle groups items per "recipe reference", include the recipe revision, like ``app1/0.1@#584778f98ba1d0eb7c80a5ae1fe12fe2``. For each one, it will list all different binaries, identified by their ``package_id`` that are involved in the different lockfiles, listing all lockfiles for each ``package_id``. In this case, as ``app1`` only belongs to app1 lockfiles, only -one lockfile ``app1_windows.lock``, ``app1_linux.lock`` is in each ``package_id``. Also the package revision ``prev`` is listed, +one lockfile ``app1_windows.lock``, ``app1_linux.lock`` is in each ``package_id``. Also, the package revision ``prev`` is listed, in this case being null, because there is no locked binary in the lockfiles, but is going to be built. .. note:: From 6d0741bd85acc4d4b5bf9f8f075d024c937fdd83 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 25 Feb 2021 16:27:46 +0100 Subject: [PATCH 5/6] Update versioning/lockfiles/bundle.rst Co-authored-by: Carlos Zoido --- versioning/lockfiles/bundle.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versioning/lockfiles/bundle.rst b/versioning/lockfiles/bundle.rst index d88f7d39841..23410c88795 100644 --- a/versioning/lockfiles/bundle.rst +++ b/versioning/lockfiles/bundle.rst @@ -90,7 +90,7 @@ The bundle groups items per "recipe reference", include the recipe revision, lik For each one, it will list all different binaries, identified by their ``package_id`` that are involved in the different lockfiles, listing all lockfiles for each ``package_id``. In this case, as ``app1`` only belongs to app1 lockfiles, only one lockfile ``app1_windows.lock``, ``app1_linux.lock`` is in each ``package_id``. Also, the package revision ``prev`` is listed, -in this case being null, because there is no locked binary in the lockfiles, but is going to be built. +in this case being ``null``, because there is no locked binary in the lockfiles, but is going to be built. .. note:: From 979ebe42999a0f9cd5ce48fa69642e7d2678e551 Mon Sep 17 00:00:00 2001 From: James Date: Thu, 25 Feb 2021 16:28:03 +0100 Subject: [PATCH 6/6] Update versioning/lockfiles/bundle.rst Co-authored-by: Carlos Zoido --- versioning/lockfiles/bundle.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versioning/lockfiles/bundle.rst b/versioning/lockfiles/bundle.rst index 23410c88795..ac98b496b10 100644 --- a/versioning/lockfiles/bundle.rst +++ b/versioning/lockfiles/bundle.rst @@ -86,7 +86,7 @@ Inspecting the resulting lockfile bundle file, we can see it is a json file with ] }, -The bundle groups items per "recipe reference", include the recipe revision, like ``app1/0.1@#584778f98ba1d0eb7c80a5ae1fe12fe2``. +The bundle groups items per "recipe reference", included the recipe revision, like ``app1/1.1@#584778f98ba1d0eb7c80a5ae1fe12fe2``. For each one, it will list all different binaries, identified by their ``package_id`` that are involved in the different lockfiles, listing all lockfiles for each ``package_id``. In this case, as ``app1`` only belongs to app1 lockfiles, only one lockfile ``app1_windows.lock``, ``app1_linux.lock`` is in each ``package_id``. Also, the package revision ``prev`` is listed,