|
| 1 | +# Servicing Granularity - Rejected Approaches |
| 2 | +See [README.md](README.md) for context on the servicing granularity problem. |
| 3 | +This document discusses rejected approaches. |
| 4 | + |
| 5 | +# Switching to microsoft build granularity |
| 6 | +This section discusses the consequences of switching to the very granular |
| 7 | +Microsoft servicing policy. |
| 8 | + |
| 9 | +## Background: granularity of the Microsoft servicing build |
| 10 | +How granular is the Microsoft build really? Each dotnet repo is generally a |
| 11 | +product, but some repositories go further, containing multiple products in a |
| 12 | +single source tree. This is an example based on 3.0 (some products may be |
| 13 | +missing from the list): |
| 14 | + |
| 15 | +* CoreFX |
| 16 | + * The NETCoreApp shared framework implementation (product) |
| 17 | + * `runtime.linux-x64.Microsoft.Private.CoreFx.NETCoreApp` |
| 18 | + * Always built when NETCoreApp gets any patch. |
| 19 | + * The out of band (OOB) packages (*each* is a product) |
| 20 | + * `System.Data.SqlClient` |
| 21 | + * `System.Diagnostics.EventLog` |
| 22 | + * `System.Drawing.Common` |
| 23 | + * `System.IO.Pipelines` |
| 24 | + * `System.IO.Ports` |
| 25 | + * ...more. These `System.*` packages are produced in CoreFX, but aren't |
| 26 | + included in the NETCoreApp framework. Some are used by downstream |
| 27 | + frameworks like ASP.NET Core, and by the tools and SDK. They are also used |
| 28 | + by apps directly via `PackageReference`. |
| 29 | + * These are somewhat likely to get patches over time. |
| 30 | + |
| 31 | +* Core-Setup |
| 32 | + * The NETCoreApp shared framework and Runtime/AppHost pack (product) |
| 33 | + * `Microsoft.NETCore.App.Runtime.linux-x64` |
| 34 | + * Always built when NETCoreApp gets any patch. |
| 35 | + * The NETCoreApp Targeting pack (product) |
| 36 | + * NETStandard Targeting pack (product) |
| 37 | + * Targeting packs are unlikely to get patches. |
| 38 | + |
| 39 | +* AspNetCore |
| 40 | + * ASP.NET Core shared framework and Runtime pack (product) |
| 41 | + * `Microsoft.AspNetCore.App.Runtime.linux-x64` |
| 42 | + * ASP.NET Core Targeting pack (product) |
| 43 | + |
| 44 | +This means if you assemble a dependency graph of a theoretical .NET Core SDK, |
| 45 | +say 3.0.103, it will contain multiple versions of the same repos: |
| 46 | + |
| 47 | +* .NET Core SDK `v3.0.103` |
| 48 | + * CoreFX |
| 49 | + * `v3.0.3` - System.Security.Permissions, shared framework implementation |
| 50 | + * `v3.0.2` - System.ServiceProcess.ServiceController |
| 51 | + * `v3.0.1` - System.Security.Cryptography.Xml |
| 52 | + * `v3.0.0` - System.IO.Pipelines |
| 53 | + * [...] |
| 54 | + |
| 55 | +This shows how the number of nodes will naturally grow over time. The max number |
| 56 | +of versions of a specific repo is bounded by the number of products it builds. |
| 57 | +The max is only three for Core-Setup, but larger (dozens?) for CoreFX because of |
| 58 | +the number of independent OOB packages. |
| 59 | + |
| 60 | +## Consequences of depending on multiple versions of the same repo |
| 61 | + |
| 62 | +### Microsoft builds |
| 63 | +This is completely fine for Microsoft servicing builds, because they use |
| 64 | +prebuilts. When building a repo, all upstream products are downloaded from an |
| 65 | +online source, so the *version* of each product isn't important. |
| 66 | + |
| 67 | +### Building from source |
| 68 | +Multiple versions of the same repo has significant consequences for |
| 69 | +source-build, on the other hand. Downloading prebuilt products is forbidden, so |
| 70 | +every upstream product must be built from source. The more commits built, the |
| 71 | +longer the build takes. |
| 72 | + |
| 73 | +In some cases, we can redistribute the previous source-built binaries, but we |
| 74 | +have to account for bootstrapping on new distros (no previous source-build |
| 75 | +exists) and distros that don't keep old binaries around: |
| 76 | + |
| 77 | +> Some (not all) Linux distribution do keep around older distro packages in |
| 78 | +their distro repository (eg, we build source-build 3.0.10, and 3.0.9 is still |
| 79 | +around for installation). If that was a general policy (it's not, for example, |
| 80 | +in Fedora) than source-build could do what Microsoft build does and use older |
| 81 | +builds. Aside from being not being supported everywhere, it also means |
| 82 | +source-build needs previous patch versions to have been built in that distro |
| 83 | +too. A new distro couldn't skip packaging 3.0.0 if 3.0.10 still needs something |
| 84 | +from there. [[omajid's review |
| 85 | +comment](https://github.com/dotnet/source-build/pull/1389#discussion_r350783942)] |
| 86 | + |
| 87 | +Even worse, the number of dependency nodes will tend to increase over time as a |
| 88 | +branch gets serviced, as demonstrated above with the list of tags comprising a |
| 89 | +theoretical `v3.0.103` SDK. This means the difficulty and complexity of building |
| 90 | +.NET Core would then depend on how many times the branch has had a servicing |
| 91 | +release. |
| 92 | + |
| 93 | +A few concrete reasons this causes significant overhead and/or upfront work for |
| 94 | +source-build infra maintainers: |
| 95 | + |
| 96 | +1. Say a new distro appears that can't build anything earlier than CoreFX |
| 97 | + `v3.0.3`, but we need to bootstrap .NET Core. To build the required `v3.0.0`, |
| 98 | + `v3.0.1`, and `v3.0.2` tags, we must add patches to each one to get them to |
| 99 | + build. The patching work *probably* only needs to be done once and applied on |
| 100 | + all affected commits, but as the release branch continues to be serviced, the |
| 101 | + amount of work to get the product built on a new distro compounds. |
| 102 | +2. Each repo must be checked out at every required commit/tag, which syncs a |
| 103 | + *lot* of irrelevant source code. |
| 104 | +3. The repo must either be built in its entirety, or we need significant infra |
| 105 | + work to allow source-build to pick the exact product it needs to build. |
| 106 | + |
| 107 | +## Q&A |
| 108 | + |
| 109 | +### Can we split up source-build products to make this less difficult? |
| 110 | +The thought here is that we might be able to split source-build into more |
| 111 | +tarballs with more intermediate distro packages. This could reduce the amount of |
| 112 | +code being compiled at once, making the build more incremental. |
| 113 | + |
| 114 | +There is direct feedback from experienced distro maintainers that we need to |
| 115 | +keep it simple: continue building a ".NET Core SDK + Runtime" product. Asking |
| 116 | +distro maintainers to keep track of many products is a significant burden and |
| 117 | +expected to cause mistakes. |
| 118 | + |
| 119 | +This also doesn't solve (1) from above. We would still need to add patches to |
| 120 | +old, unmaintained tags to bring up .NET Core on a new distro. |
| 121 | + |
| 122 | +### Does source-build-reference-packages help? |
| 123 | +Context: any NuGet package that only contains references can be built by |
| 124 | +[dotnet/source-build-reference-packages](https://github.com/dotnet/source-build-reference-packages) |
| 125 | +rather than checking out and building the original repo. In some cases, such as |
| 126 | +targeting packs, we already do this. |
| 127 | + |
| 128 | +This doesn't work for CoreFX OOB packages, which contain implementation. The OOB |
| 129 | +packages are a particular pain point with this approach, so |
| 130 | +source-build-reference-packages doesn't help significantly. |
0 commit comments