From 1ec992f294178c96492ee61024ef00692b62f0ad Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Thu, 20 Jan 2022 12:47:24 -0600 Subject: [PATCH 01/16] Add guidance for new dependencies --- .../sourcebuild-in-repos/new-dependencies.md | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 Documentation/sourcebuild-in-repos/new-dependencies.md diff --git a/Documentation/sourcebuild-in-repos/new-dependencies.md b/Documentation/sourcebuild-in-repos/new-dependencies.md new file mode 100644 index 0000000000..f5170bc416 --- /dev/null +++ b/Documentation/sourcebuild-in-repos/new-dependencies.md @@ -0,0 +1,32 @@ +# Adding a new dependency + +## Basics +When adding a new dependency, there are a few steps common between any type of dependency. If you use darc, `darc add-dependency` will take care of this process for you. Otherwise: +1. Add the package and a default version to eng/Versions.props. The default version property should be named `PackageVersion`, e.g. `SystemCollectionsImmutablePackageVersion`. +2. Add the package and a repo reference to eng/Version.Details.xml. +3. Set up dependency flow from the foreign repo to your repo. + +In general, you should aim to use one version of each package. If you are using a package as reference-only, it is possible to use multiple versions, but only one implementation version of each package will be used - source-build will override it to the version that is being built in this version of the SDK. + +## Deciding what version to use +- If you are using the package as reference-only and want the version to be pinned, use a literal version number in the csprojs that reference the project. You can also set up a reference-only package version variable in eng/Versions.props, for instance `1.2.3` in addition to `4.5.6`. Also verify that the package is available in source-build-reference-packages, and if not, contact the source-build team. +- If you are using the package in the actual build or want the version to be updated whenever the foreign repo publishes to your channel, use the version number property set up in eng/Versions.props. This will be overridden in some cases by source-build. + +## Internal dependencies +Adding a new dotnet dependency is usually pretty straightforward but does have some edge cases. Use this checklist: +1. Are you already using a package from the same repo? + 1. This is the simplest case. You can add new dependencies from repos you are already using freely. +2. Is this a Microsoft repo that uses Arcade to build? + 1. Does the foreign repo depend on your repo, directly or indirectly? i.e. would adding the dependency create a cycle? + 1. This isn't necessarily a deal-breaker - it can sometimes be worked around with reference-only packages. Please contact a source-build team member to discuss. + 2. Does the foreign repo publish to BAR? + 1. If not, please contact them to get them publishing to BAR in an appropriate channel. + 3. If neither of these caveats apply you should be in good shape. Follow the instructions under "Basics" above. +3. Source-build has in the past used Arcade shims to allow non-Arcade repos to build appropriate packages for source-build. Please contact the source-build team to determine if this is a workable approach for your foreign repo. + +## External dependencies + +External (non-Microsoft or even non-dotnet) dependencies need to be carefully considered for source-build in addition to the licensing issues you are probably already familiar with. +1. Microsoft but non-dotnet repos should usually be able to use the same Arcade wrapper to publish appropriate packages for source-build - please contact a source-build team member to discuss. +2. Dependencies that have no code (e.g. SDKs with just props and targets) can usually be added using the source-build text-only-package process. Contact a source-build team member for more information. +3. We build some external dependencies in the dotnet/source-build repo. Good targets for this generally have very few if any dependencies and very simple build processes. Contact a source-build team member for more information. \ No newline at end of file From b0ea2ed9e7fef848e66f39587dc2a3ee5fc8dab5 Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Thu, 20 Jan 2022 14:48:19 -0600 Subject: [PATCH 02/16] Instructions for upating dependencies. --- .../sourcebuild-in-repos/new-dependencies.md | 3 ++- .../update-dependencies.md | 23 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 Documentation/sourcebuild-in-repos/update-dependencies.md diff --git a/Documentation/sourcebuild-in-repos/new-dependencies.md b/Documentation/sourcebuild-in-repos/new-dependencies.md index f5170bc416..bf20124ab3 100644 --- a/Documentation/sourcebuild-in-repos/new-dependencies.md +++ b/Documentation/sourcebuild-in-repos/new-dependencies.md @@ -10,7 +10,8 @@ In general, you should aim to use one version of each package. If you are using ## Deciding what version to use - If you are using the package as reference-only and want the version to be pinned, use a literal version number in the csprojs that reference the project. You can also set up a reference-only package version variable in eng/Versions.props, for instance `1.2.3` in addition to `4.5.6`. Also verify that the package is available in source-build-reference-packages, and if not, contact the source-build team. -- If you are using the package in the actual build or want the version to be updated whenever the foreign repo publishes to your channel, use the version number property set up in eng/Versions.props. This will be overridden in some cases by source-build. +- If you are using the package in the actual build or want the version to be updated whenever the foreign repo publishes to your channel, use the version number property set up in eng/Versions.props. This will be overridden in some cases by source-build. +- If you are using an external or non-Arcade package, please coordinate as much as possible with other teams using that package. Each package-version is essentially maintained as a separate concern, so something like repo A requiring Newtonsoft.Json 9.0.1 and repo B requiring 12.0.2 essentially doubles the source-build team's work. ## Internal dependencies Adding a new dotnet dependency is usually pretty straightforward but does have some edge cases. Use this checklist: diff --git a/Documentation/sourcebuild-in-repos/update-dependencies.md b/Documentation/sourcebuild-in-repos/update-dependencies.md new file mode 100644 index 0000000000..0b67ee41b1 --- /dev/null +++ b/Documentation/sourcebuild-in-repos/update-dependencies.md @@ -0,0 +1,23 @@ +# Updating a dependency + +In most cases, dependency flow should automatically update the packages you depend on. There are some special considerations and things to keep in mind when doing manual updates. + +## External packages + +Updating a non-Microsoft or non-Arcade package is typically equivalent to adding the new version all over again. Please contact a source-build team member to discuss this. + +## Internal packages + +If you are manually updating a package, please make sure it's from a compatible branch (e.g. runtime release/6.0 to sdk release/6.0.1xx, release/6.0.2xx, etc). Package versions that you are updating to should be source-built in their respective repos. If the version you need is produced in a branch that is not yet source-build-compatible please let the source-build team know. + +## Splitting, combining, and moving packages + +These operations often end up causing source-build issues. A typical case of what can happen is +1. Package A is produced in version 1. +2. In version 2, Package A is split into Package A1 and Package A2. +3. A downstream repo is never updated to take the split packages. +4. The version 2 source-build succeeds because Package A exists in the previously-source-built archive, but no new version of Package A is produced. +5. Source-build version 3 fails because Package A no longer exists in the previously-source-built archive either. + + +So please keep in mind consumers of your packages and try to keep them informed of these kinds of changes. If you are the consuming repo, consider tracking PRs in the repos that produce your dependencies. \ No newline at end of file From e6d7c3ef8c06b1d33ddb218da0e847178085a850 Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Thu, 20 Jan 2022 15:05:15 -0600 Subject: [PATCH 03/16] Guidance for new features --- .../sourcebuild-in-repos/adding-features.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 Documentation/sourcebuild-in-repos/adding-features.md diff --git a/Documentation/sourcebuild-in-repos/adding-features.md b/Documentation/sourcebuild-in-repos/adding-features.md new file mode 100644 index 0000000000..043bb83e9c --- /dev/null +++ b/Documentation/sourcebuild-in-repos/adding-features.md @@ -0,0 +1,15 @@ +# New features + +New features are great! They also have source-build considerations though. .NET is no longer just multi-platform but also multi-distribution: there's a Linux SDK produced by Microsoft, but there's also a Linux SDK produced by Red Hat, one produced by Fedora, and one that anyone in the community can build himself from source. + +## Things to consider + +New features, or expansions of current features, should act sensibly across Windows, Linux, and OSX. This also involves taking into account the limitations and conventions of the different platforms - for instance, on Linux, it's typical for the .NET SDK to be installed by root and therefore be unchangeable by normal users, so installing global tools needs to take into account the fact that the user might not be able to add anything to the SDK directories. + +XXX details on the global tools issues + +New features also need to be compatible across all distributions of .NET - for instance, Fedora and Debian cannot distribute *any* non-open-source code, even samples, tests, or minor additions to licenses like restricting the field that the code can be used in. This includes any code or packages that are used to build product code as well. + +XXX fill in the details on dotnet-check/dotnet-format here + +XXX Should we create a Github group for source-build community members that would be interested in reviewing things like this? \ No newline at end of file From df97e8148d69af530a5d47699940c6cca0ab14af Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Thu, 20 Jan 2022 15:24:24 -0600 Subject: [PATCH 04/16] Add general build info guidance. --- Documentation/sourcebuild-in-repos/build-info.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Documentation/sourcebuild-in-repos/build-info.md diff --git a/Documentation/sourcebuild-in-repos/build-info.md b/Documentation/sourcebuild-in-repos/build-info.md new file mode 100644 index 0000000000..17f3cdc75d --- /dev/null +++ b/Documentation/sourcebuild-in-repos/build-info.md @@ -0,0 +1,13 @@ +# Source-build build info + +This is a collection of notes about how source-build can differ in general from your repo's build and what kind of issues that can create. + +## Single-version and single-RID build + +Source-build is required to build on a single machine with no internet access. This means that we build targeting a single RID, usually the non-portable RID for the build machines (like rhel.7-x64). We do support building portable (linux-x64) as well - this is useful for bootstrapping new distributions. + +We also only build one version of each repo. This means that if your repo turns production of some packages on and off, for instance, if you only produce packages if they are changed, source-build will need a workaround to force all packages to be produced. Additionally, we can only supply one version of each package to a repo. This is injected into the `$(PackageVersion)` variables. The exception is reference-only packages - dotnet/source-build-reference-packages produces multiple versions and these can be hard-coded or use a `$(ReferenceVersion)` property or similar if you don't need source-build to change them. + +## No Windows-specific packages + +Packages that require Windows components or references cannot be built in source-build. These should use `true` or other options to be excluded from the source-build. \ No newline at end of file From c118fc13e3963a3a10da47be9e7af397ceaa79e4 Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Thu, 20 Jan 2022 15:26:51 -0600 Subject: [PATCH 05/16] Add index. --- Documentation/sourcebuild-in-repos/README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 Documentation/sourcebuild-in-repos/README.md diff --git a/Documentation/sourcebuild-in-repos/README.md b/Documentation/sourcebuild-in-repos/README.md new file mode 100644 index 0000000000..9422e8c7bb --- /dev/null +++ b/Documentation/sourcebuild-in-repos/README.md @@ -0,0 +1,10 @@ +# Repo owner's handbook for source-build + +These docs aim to be a collection of useful information for repo owners who work with and participate in source-build. + +## Index + +[Adding new dependencies](new-dependencies.md) +[Updating dependencies](update-dependencies.md) +[Considerations when adding features](adding-features.md) +[General notes on the source-build build](build-info.md) \ No newline at end of file From c5d7e202c636f27c76e72958b15835748520d4aa Mon Sep 17 00:00:00 2001 From: Michael Simons Date: Tue, 1 Mar 2022 10:41:06 -0600 Subject: [PATCH 06/16] Add onboarding new repo documentation --- Documentation/sourcebuild-in-repos/README.md | 9 +- .../sourcebuild-in-repos/img/ci-job.png | Bin 0 -> 43219 bytes .../onboarding-new-repo.md | 255 ++++++++++++++++++ 3 files changed, 260 insertions(+), 4 deletions(-) create mode 100644 Documentation/sourcebuild-in-repos/img/ci-job.png create mode 100644 Documentation/sourcebuild-in-repos/onboarding-new-repo.md diff --git a/Documentation/sourcebuild-in-repos/README.md b/Documentation/sourcebuild-in-repos/README.md index 9422e8c7bb..0ba930196a 100644 --- a/Documentation/sourcebuild-in-repos/README.md +++ b/Documentation/sourcebuild-in-repos/README.md @@ -4,7 +4,8 @@ These docs aim to be a collection of useful information for repo owners who work ## Index -[Adding new dependencies](new-dependencies.md) -[Updating dependencies](update-dependencies.md) -[Considerations when adding features](adding-features.md) -[General notes on the source-build build](build-info.md) \ No newline at end of file +* [Adding new dependencies](new-dependencies.md) +* [Updating dependencies](update-dependencies.md) +* [Considerations when adding features](adding-features.md) +* [General notes on the source-build build](build-info.md) +* [Adding new repositories](new-repo.md) diff --git a/Documentation/sourcebuild-in-repos/img/ci-job.png b/Documentation/sourcebuild-in-repos/img/ci-job.png new file mode 100644 index 0000000000000000000000000000000000000000..398208ca2892088ebd31aaf36cd5461b6bd86aa9 GIT binary patch literal 43219 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 literal 0 HcmV?d00001 diff --git a/Documentation/sourcebuild-in-repos/onboarding-new-repo.md b/Documentation/sourcebuild-in-repos/onboarding-new-repo.md new file mode 100644 index 0000000000..6246f70ab2 --- /dev/null +++ b/Documentation/sourcebuild-in-repos/onboarding-new-repo.md @@ -0,0 +1,255 @@ +# Adding a new repository to source build + +This document describes the overall process of onboarding new repos onto arcade powered source build (ArPow). For more details about how the build executes, see +[dotnet/arcade/.../Microsoft.DotNet.Arcade.Sdk/tools/SourceBuild](https://github.com/dotnet/arcade/tree/master/src/Microsoft.DotNet.Arcade.Sdk/tools/SourceBuild). +The source code for the build tasks that run for prebuilt validation and intermediate nupkg dependency reading are maintained at +[dotnet/arcade/.../Microsoft.DotNet.SourceBuild](https://github.com/dotnet/arcade/tree/master/src/Microsoft.DotNet.SourceBuild). + +1. [Source Build Configuration](#source-build-configuration) +1. [Setup CI](#setup-ci) +1. [Add Downstream Dependency](#add-downstream-dependency) +1. [Validate](##validate) + +## Source Build Configuration + +Configuring source build involves setting up files in `eng/` that determine the behavior of source-build in the repo. + +These changes are all needed before the inner source-build will work: + +* [`eng/SourceBuild.props`](#engsourcebuildprops) - Basic properties, such as repo name. +* [`eng/SourceBuildPrebuiltBaseline.xml`](#engsourcebuildprebuiltbaselinexml) - Allow prebuilts. Until prebuilt detection is enabled/enforced, we allow all + prebuilts. +* [`eng/Version.Details.xml`](#engversiondetailsxml) - Already exists, but modifications are needed to pull dependencies from upstream intermediate nupkgs. + +See the following sections for details: + +### `eng/SourceBuild.props` + +```xml + + + + this-repo + true + + + +``` + +This file contains basic configuration used to restore the correct dependencies (managed-only or not) and produce the right name for the repo's [intermediate +nupkg]. + +* `this-repo` should be the same as the repo's name on GitHub, without the GitHub organization name. +* `SourceBuildManagedOnly` defaults to false if omitted. `true` means that the repo doesn't produce any RID-specific artifacts like + `Microsoft.NETCore.App.Runtime.linux-x64`, only managed code. + +These two properties determine the name of the [intermediate nupkg]: `Microsoft.SourceBuild.Intermediate.$(GitHubRepositoryName)[.$(RidSuffix)]`. + +It's possible more configuration will be required for specific repos. `eng/SourceBuild.props`, similar to `eng/Build.props`, is a place to add extra +MSBuild code that can change the way source-build behaves. + +### `eng/SourceBuildPrebuiltBaseline.xml` + +```xml + + + + + +``` + +This defines which prebuilt NuGet packages are allowed to be used during thebuild. Initially, all package IDs and versions are permitted (`*/*`). + +The `*/*` glob means "any nupkg id, any version". It will be replaced with more specific rules at a later phase of the implementation plan. The goal is to make +it specific, so when a PR introduces an unexpected prebuilt, PR validation will fail and let us resolve the source-buildability issue before the PR gets merged. + +### Trying it out locally + +After setting up ArPow in a repo, running it locally is done by passing `/p:ArcadeBuildFromSource=true` at the end of the usual +arcade-based build command for the repo. For example: + +```bash +./build.sh -c Release --restore --build --pack /p:ArcadeBuildFromSource=true -bl +``` + +> Note: [source-build is not supported on Windows](https://github.com/dotnet/source-build/issues/1190), only Linux and macOS. + +After running the build, source-build artifacts will be in `artifacts/source-build`, and the [intermediate nupkg] will be something like +`artifacts/packages/*/Microsoft.SourceBuild.Intermediate.*.nupkg`. + +The MSBuild binlog will be placed somewhere like: `artifacts/log/Debug/Build.binlog`. However, this "outer" binlog doesn't contain +the meat of the build: the "inner" build runs inside an `Exec` task. The inner binlog will be written to: +`artifacts/source-build/self/src/artifacts/sourcebuild.binlog`. + +### Excluding components + +It is not always necessary or correct to include all repo components in source-build. Examples include tests, Windows components +(rmember source build currently only supports Linux and macOS), etc. Including such components introduce prebuilts. To exlcude these components +utilize the `DotNetBuildFromSource` msbuild property to conditionally exclude these components. + +```code +Condition="'$(DotNetBuildFromSource)' != 'true'" +``` + +### `eng/Version.Details.xml` + +```xml +... + + https://github.com/dotnet/runtime + a820ca1c4f9cb5892331e2624d3999c39161fe2a + + +... + + https://github.com/dotnet/source-build-reference-packages + def2e2c6dc5064319250e2868a041a3dc07f9579 + + +... +``` + +Dependency changes may include adding `SourceBuild` to existing dependency elements, and adding a new `source-build-reference-packages` element. + +`SourceBuild` causes the source-build targets in the Arcade SDK to download [intermediate nupkg]s from the upstream repo's official build, rather than using +prebuilt binaries to fulfill the dependencies. Note that `RepoName` is used to calculate the ID of the [intermediate nupkg]: the `Dependency` `Name` is +ignored by source-build. + +`ManagedOnly` determines whether a RID suffix is necessary on the [intermediate nupkg] ID. For example, running source-build on `dotnet/installer` with +`linux-x64` with the above example configuration will restore: + +* `Microsoft.SourceBuild.Intermediate.runtime.linux-x64` + * `.linux-x64` because `ManagedOnly` is not `true`. +* `Microsoft.SourceBuild.Intermediate.source-build-reference-packages` + * Ends with the `RepoName` without a suffix because `ManagedOnly="true"`. + +## Setup CI + +ArPow needs to run during official builds to create source-build [intermediate nupkg]s for the downstream repos that will +consume them. ArPow should also run in PR validation builds, to prevent regression in the ArPow flow. + +The ArPow implementation can be activated with a single flag in the ordinary Arcade SDK jobs template for easy consumption. If a repo can't simply use the +Arcade SDK jobs template, more granular templates are also available. + +See for the current template source code. The inline comments in the `parameters:` section +in those files are the most up to date docs, maintained with higher priority than this general onboarding doc. + +### `eng/common/templates/jobs/jobs.yml` opt-in switch + +The simplest way to onboard. This approach applies if the repo already uses the `eng/common/templates/jobs/jobs.yml` template. + +To opt in: + +#### 1: Set `enableSourceBuild: true` + +Set `enableSourceBuild: true` in the template parameters. + +This should look something like [this sourcelink implementation:](https://github.com/dotnet/sourcelink/blob/dfe619dc722be42d475595c755c958afe6177554/azure-pipelines.yml#L40) + +```yaml +stages: +- stage: build + displayName: Build + jobs: + - template: /eng/common/templates/jobs/jobs.yml + parameters: + enablePublishUsingPipelines: true + enablePublishBuildArtifacts: true + enablePublishBuildAssets: true + enableSourceBuild: true + artifacts: + publish: + artifacts: true + manifests: true +``` + +#### 2: Specify platforms (if repo is not managed-only) + +A repo is managed-only if `eng/SourceBuild.props` contains `true`. If this is true, this +step is not necessary. Otherwise, specify `sourceBuildParameters` in the `jobs.yml` template's parameters like this: + +```yaml +sourceBuildParameters: + platforms: + - name: 'Centos71_Portable' + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-3e800f1-20190501005343' + - name: 'MacOS_Portable' + pool: { vmImage: 'macOS-10.14' } + - name: 'Centos71' + nonPortable: true + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-3e800f1-20190501005343' + - name: 'Centos8' + nonPortable: true + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-daa5116-20200325130212' + - name: 'Debian9' + nonPortable: true + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:debian-stretch-20200918130533-047508b' + - name: 'Fedora30' + nonPortable: true + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-30-38e0f29-20191126135223' + - name: 'Fedora32' + nonPortable: true + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-32-20200512010618-163ed2a' + - name: 'MacOS' + nonPortable: true + pool: { vmImage: 'macOS-10.14' } + - name: 'Ubuntu1804' + nonPortable: true + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-20200918145614-047508b' +``` + +#### End result + +Submit the changes above in a PR and add [@source-build-internal](https://github.com/orgs/dotnet/teams/source-build-internal) as a reviewer. The jobs (or job, if managed-only) are automatically be added to CI in the existing pipeline alongside existing jobs, +with a name like `Build Source-Build ()`: + +![Build jobs image with source build leg](img/ci-job.png) + +Once this PR works, run a mock official build (AKA "validation build") in your official build definition. The usual workflow is to push a `dev//arpow` branch to the AzDO repo and then queue a build on that branch. This makes sure that merging the PR won't immediately break the official build: +`enableSourceBuild: true` does add job(s) to the official build, not just PR validation. + +If the PR is green, but merging it produces red PR or Official builds, immediately let the source-build team know about the failure and revert the +source-build PR to unblock dev work. + +### Advanced: granular templates + +If the repo doesn't use the basic Arcade jobs template, or has advanced job templating infra built on top of the Arcade jobs template, the simple +`enableSourceBuild` flag might not work out. There are a few more granular templates to use in this case. + +Look at the documentation in each YAML file itself to figure out how to use it properly, and if it fits the scenario. This list is only an overview. + +#### `eng/common/templates/jobs/source-build.yml` + +This is one level deeper than `eng/common/templates/jobs/jobs.yml`. It is a `jobs` template that produces just the set of source-build jobs based on the +specified `platforms`. Or, just one job with the default platform, if managed-only. + +#### `eng/common/templates/job/source-build.yml` + +This template defines a single `job` that runs source-build on a specifiedplatform. + +#### `eng/common/templates/steps/source-build.yml` + +This template defines the build `steps` for a single source-build job. This is the most granular template, and may be useful if some repo-specific preamble or +cleanup steps are required, or if the repo already has job matrix templates and this just happens to fit in nicely. + +### Official build publishing + +Publishing [intermediate nupkg]s in the official build is handled by the standard Arcade publish infrastructure, which should already be set up in the +repo. The source-build steps handle uploading the [intermediate nupkg] to the pipeline in the standard way that Arcade will detect and publish. + +[intermediate nupkg]: https://github.com/dotnet/source-build/blob/master/Documentation/planning/arcade-powered-source-build/intermediate-nupkg.md + +## Add Downstream Dependency + +The graph defined by `eng/Version.Details.xml` defines what is included in source-build. This dependency graph starts at +[dotnet/installer](https://github.com/dotnet/installer/blob/main/eng/Version.Details.xml). The .NET source build insfrastructure walks this graph and determines +the full set of repos to build. Source build will only build one copy/commit of each repo (the first commit found in the dependency graph). Therefore, when adding +a new repositories, a dependency must be created within the `eng/Version.Details.xml` graph. To do this, go to the repo which depends on the new repo and add a [new +source build dependency](#eng/Version.Details.xml). + +## Validate + +Once the downstream dependency(s) are added to the new repo and those changes flow into `dotnet/installer`, a complete .NET source tarball can be build. +This will validate that now prebuilts we added to the system and everything is functioning correctly. Please notify +[@source-build-internal](https://github.com/orgs/dotnet/teams/source-build-internal) to be on the lookout for the new repo and they will validate as necessary. From f5b66285ee08851c4490e226165a24f596bd4804 Mon Sep 17 00:00:00 2001 From: Michael Simons Date: Tue, 1 Mar 2022 11:05:08 -0600 Subject: [PATCH 07/16] onboard new repo cleanup --- .../onboarding-new-repo.md | 161 +++++++++--------- 1 file changed, 81 insertions(+), 80 deletions(-) diff --git a/Documentation/sourcebuild-in-repos/onboarding-new-repo.md b/Documentation/sourcebuild-in-repos/onboarding-new-repo.md index 6246f70ab2..7e5a70cf88 100644 --- a/Documentation/sourcebuild-in-repos/onboarding-new-repo.md +++ b/Documentation/sourcebuild-in-repos/onboarding-new-repo.md @@ -12,9 +12,9 @@ The source code for the build tasks that run for prebuilt validation and interme ## Source Build Configuration -Configuring source build involves setting up files in `eng/` that determine the behavior of source-build in the repo. +Configuring source build involves setting up files in `eng/` that determine the behavior of source build in the repo. -These changes are all needed before the inner source-build will work: +These changes are all needed before the inner source build will work: * [`eng/SourceBuild.props`](#engsourcebuildprops) - Basic properties, such as repo name. * [`eng/SourceBuildPrebuiltBaseline.xml`](#engsourcebuildprebuiltbaselinexml) - Allow prebuilts. Until prebuilt detection is enabled/enforced, we allow all @@ -46,7 +46,7 @@ nupkg]. These two properties determine the name of the [intermediate nupkg]: `Microsoft.SourceBuild.Intermediate.$(GitHubRepositoryName)[.$(RidSuffix)]`. It's possible more configuration will be required for specific repos. `eng/SourceBuild.props`, similar to `eng/Build.props`, is a place to add extra -MSBuild code that can change the way source-build behaves. +MSBuild code that can change the way source build behaves. ### `eng/SourceBuildPrebuiltBaseline.xml` @@ -60,8 +60,9 @@ MSBuild code that can change the way source-build behaves. This defines which prebuilt NuGet packages are allowed to be used during thebuild. Initially, all package IDs and versions are permitted (`*/*`). -The `*/*` glob means "any nupkg id, any version". It will be replaced with more specific rules at a later phase of the implementation plan. The goal is to make -it specific, so when a PR introduces an unexpected prebuilt, PR validation will fail and let us resolve the source-buildability issue before the PR gets merged. +The `*/*` glob means "any nupkg id, any version". It will be replaced with more specific rules at a later phase once the repo level prebuilt detection +infrastructure is completed. The goal is to make it specific, so when a PR introduces an unexpected prebuilt, PR validation will fail and let us resolve +the source-buildability issue before the PR gets merged. ### Trying it out locally @@ -72,9 +73,9 @@ arcade-based build command for the repo. For example: ./build.sh -c Release --restore --build --pack /p:ArcadeBuildFromSource=true -bl ``` -> Note: [source-build is not supported on Windows](https://github.com/dotnet/source-build/issues/1190), only Linux and macOS. +> Note: [source build is not supported on Windows](https://github.com/dotnet/source-build/issues/1190), only Linux and macOS. -After running the build, source-build artifacts will be in `artifacts/source-build`, and the [intermediate nupkg] will be something like +After running the build, source build artifacts will be in `artifacts/source-build`, and the [intermediate nupkg] will be something like `artifacts/packages/*/Microsoft.SourceBuild.Intermediate.*.nupkg`. The MSBuild binlog will be placed somewhere like: `artifacts/log/Debug/Build.binlog`. However, this "outer" binlog doesn't contain @@ -83,9 +84,9 @@ the meat of the build: the "inner" build runs inside an `Exec` task. The inner b ### Excluding components -It is not always necessary or correct to include all repo components in source-build. Examples include tests, Windows components -(rmember source build currently only supports Linux and macOS), etc. Including such components introduce prebuilts. To exlcude these components -utilize the `DotNetBuildFromSource` msbuild property to conditionally exclude these components. +It is not always necessary or correct to include all repo components in source build because they introduce prebuilt that cannot be source built. +Examples include tests, Windows components (rmember source build currently only supports Linux and macOS), etc. To exlcude these components +use the `DotNetBuildFromSource` msbuild property to conditionally exclude. ```code Condition="'$(DotNetBuildFromSource)' != 'true'" @@ -111,11 +112,11 @@ Condition="'$(DotNetBuildFromSource)' != 'true'" Dependency changes may include adding `SourceBuild` to existing dependency elements, and adding a new `source-build-reference-packages` element. -`SourceBuild` causes the source-build targets in the Arcade SDK to download [intermediate nupkg]s from the upstream repo's official build, rather than using +`SourceBuild` causes the source build targets in the Arcade SDK to download [intermediate nupkg]s from the upstream repo's official build, rather than using prebuilt binaries to fulfill the dependencies. Note that `RepoName` is used to calculate the ID of the [intermediate nupkg]: the `Dependency` `Name` is -ignored by source-build. +ignored by source build. -`ManagedOnly` determines whether a RID suffix is necessary on the [intermediate nupkg] ID. For example, running source-build on `dotnet/installer` with +`ManagedOnly` determines whether a RID suffix is necessary on the [intermediate nupkg] ID. For example, running source build on `dotnet/installer` with `linux-x64` with the above example configuration will restore: * `Microsoft.SourceBuild.Intermediate.runtime.linux-x64` @@ -125,7 +126,7 @@ ignored by source-build. ## Setup CI -ArPow needs to run during official builds to create source-build [intermediate nupkg]s for the downstream repos that will +ArPow needs to run during official builds to create source build [intermediate nupkg]s for the downstream repos that will consume them. ArPow should also run in PR validation builds, to prevent regression in the ArPow flow. The ArPow implementation can be activated with a single flag in the ordinary Arcade SDK jobs template for easy consumption. If a repo can't simply use the @@ -140,67 +141,67 @@ The simplest way to onboard. This approach applies if the repo already uses the To opt in: -#### 1: Set `enableSourceBuild: true` - -Set `enableSourceBuild: true` in the template parameters. - -This should look something like [this sourcelink implementation:](https://github.com/dotnet/sourcelink/blob/dfe619dc722be42d475595c755c958afe6177554/azure-pipelines.yml#L40) - -```yaml -stages: -- stage: build - displayName: Build - jobs: - - template: /eng/common/templates/jobs/jobs.yml - parameters: - enablePublishUsingPipelines: true - enablePublishBuildArtifacts: true - enablePublishBuildAssets: true - enableSourceBuild: true - artifacts: - publish: - artifacts: true - manifests: true -``` - -#### 2: Specify platforms (if repo is not managed-only) - -A repo is managed-only if `eng/SourceBuild.props` contains `true`. If this is true, this -step is not necessary. Otherwise, specify `sourceBuildParameters` in the `jobs.yml` template's parameters like this: - -```yaml -sourceBuildParameters: - platforms: - - name: 'Centos71_Portable' - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-3e800f1-20190501005343' - - name: 'MacOS_Portable' - pool: { vmImage: 'macOS-10.14' } - - name: 'Centos71' - nonPortable: true - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-3e800f1-20190501005343' - - name: 'Centos8' - nonPortable: true - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-daa5116-20200325130212' - - name: 'Debian9' - nonPortable: true - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:debian-stretch-20200918130533-047508b' - - name: 'Fedora30' - nonPortable: true - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-30-38e0f29-20191126135223' - - name: 'Fedora32' - nonPortable: true - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-32-20200512010618-163ed2a' - - name: 'MacOS' - nonPortable: true - pool: { vmImage: 'macOS-10.14' } - - name: 'Ubuntu1804' - nonPortable: true - container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-20200918145614-047508b' -``` +1. Set `enableSourceBuild: true` + + Set `enableSourceBuild: true` in the template parameters. + + This should look something like [this sourcelink implementation:](https://github.com/dotnet/sourcelink/blob/dfe619dc722be42d475595c755c958afe6177554/azure-pipelines.yml#L40) + + ```yaml + stages: + - stage: build + displayName: Build + jobs: + - template: /eng/common/templates/jobs/jobs.yml + parameters: + enablePublishUsingPipelines: true + enablePublishBuildArtifacts: true + enablePublishBuildAssets: true + enableSourceBuild: true + artifacts: + publish: + artifacts: true + manifests: true + ``` + +1. Specify platforms (if repo is not managed-only) + + A repo is managed-only if `eng/SourceBuild.props` contains `true`. If this is true, this + step is not necessary. Otherwise, specify `sourceBuildParameters` in the `jobs.yml` template's parameters like this: + + ```yaml + sourceBuildParameters: + platforms: + - name: 'Centos71_Portable' + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-3e800f1-20190501005343' + - name: 'MacOS_Portable' + pool: { vmImage: 'macOS-10.14' } + - name: 'Centos71' + nonPortable: true + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-7-3e800f1-20190501005343' + - name: 'Centos8' + nonPortable: true + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-8-daa5116-20200325130212' + - name: 'Debian9' + nonPortable: true + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:debian-stretch-20200918130533-047508b' + - name: 'Fedora30' + nonPortable: true + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-30-38e0f29-20191126135223' + - name: 'Fedora32' + nonPortable: true + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:fedora-32-20200512010618-163ed2a' + - name: 'MacOS' + nonPortable: true + pool: { vmImage: 'macOS-10.14' } + - name: 'Ubuntu1804' + nonPortable: true + container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-20200918145614-047508b' + ``` #### End result -Submit the changes above in a PR and add [@source-build-internal](https://github.com/orgs/dotnet/teams/source-build-internal) as a reviewer. The jobs (or job, if managed-only) are automatically be added to CI in the existing pipeline alongside existing jobs, +Submit the changes above in a PR and include [@source-build-internal](https://github.com/orgs/dotnet/teams/source-build-internal) as a reviewer. The jobs (or job, if managed-only) are automatically be added to CI in the existing pipeline alongside existing jobs, with a name like `Build Source-Build ()`: ![Build jobs image with source build leg](img/ci-job.png) @@ -209,8 +210,8 @@ Once this PR works, run a mock official build (AKA "validation build") in your o alias>/arpow` branch to the AzDO repo and then queue a build on that branch. This makes sure that merging the PR won't immediately break the official build: `enableSourceBuild: true` does add job(s) to the official build, not just PR validation. -If the PR is green, but merging it produces red PR or Official builds, immediately let the source-build team know about the failure and revert the -source-build PR to unblock dev work. +If the PR is green, but merging it produces red PR or Official builds, immediately let the source build team know about the failure and revert the +source build PR to unblock dev work. ### Advanced: granular templates @@ -226,30 +227,30 @@ specified `platforms`. Or, just one job with the default platform, if managed-on #### `eng/common/templates/job/source-build.yml` -This template defines a single `job` that runs source-build on a specifiedplatform. +This template defines a single `job` that runs source build on a specifiedplatform. #### `eng/common/templates/steps/source-build.yml` -This template defines the build `steps` for a single source-build job. This is the most granular template, and may be useful if some repo-specific preamble or +This template defines the build `steps` for a single source build job. This is the most granular template, and may be useful if some repo-specific preamble or cleanup steps are required, or if the repo already has job matrix templates and this just happens to fit in nicely. ### Official build publishing Publishing [intermediate nupkg]s in the official build is handled by the standard Arcade publish infrastructure, which should already be set up in the -repo. The source-build steps handle uploading the [intermediate nupkg] to the pipeline in the standard way that Arcade will detect and publish. +repo. The source build steps handle uploading the [intermediate nupkg] to the pipeline in the standard way that Arcade will detect and publish. [intermediate nupkg]: https://github.com/dotnet/source-build/blob/master/Documentation/planning/arcade-powered-source-build/intermediate-nupkg.md ## Add Downstream Dependency -The graph defined by `eng/Version.Details.xml` defines what is included in source-build. This dependency graph starts at +The graph defined by `eng/Version.Details.xml` defines what is included in source build. This dependency graph starts at [dotnet/installer](https://github.com/dotnet/installer/blob/main/eng/Version.Details.xml). The .NET source build insfrastructure walks this graph and determines the full set of repos to build. Source build will only build one copy/commit of each repo (the first commit found in the dependency graph). Therefore, when adding a new repositories, a dependency must be created within the `eng/Version.Details.xml` graph. To do this, go to the repo which depends on the new repo and add a [new -source build dependency](#eng/Version.Details.xml). +source build dependency](#eng/Version.Details.xml) to the new source build repo. ## Validate Once the downstream dependency(s) are added to the new repo and those changes flow into `dotnet/installer`, a complete .NET source tarball can be build. -This will validate that now prebuilts we added to the system and everything is functioning correctly. Please notify +This will validate that no prebuilts we added to the system and everything is functioning correctly. Please notify [@source-build-internal](https://github.com/orgs/dotnet/teams/source-build-internal) to be on the lookout for the new repo and they will validate as necessary. From 747e3de2b4038804e5ad64764c2a053d96411809 Mon Sep 17 00:00:00 2001 From: Michael Simons Date: Tue, 1 Mar 2022 11:09:48 -0600 Subject: [PATCH 08/16] Rename new repo doc --- .../sourcebuild-in-repos/{onboarding-new-repo.md => new-repo.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/sourcebuild-in-repos/{onboarding-new-repo.md => new-repo.md} (100%) diff --git a/Documentation/sourcebuild-in-repos/onboarding-new-repo.md b/Documentation/sourcebuild-in-repos/new-repo.md similarity index 100% rename from Documentation/sourcebuild-in-repos/onboarding-new-repo.md rename to Documentation/sourcebuild-in-repos/new-repo.md From 91a6c6051bc5c14ac64d2f2f8a8611505d0baa11 Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Thu, 7 Apr 2022 12:59:07 -0500 Subject: [PATCH 09/16] Address code review comments. --- .../sourcebuild-in-repos/adding-features.md | 12 +++++++----- .../sourcebuild-in-repos/build-info.md | 10 +++++++--- .../sourcebuild-in-repos/new-dependencies.md | 17 ++++++++++++----- .../sourcebuild-in-repos/update-dependencies.md | 11 ++++++++--- 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/Documentation/sourcebuild-in-repos/adding-features.md b/Documentation/sourcebuild-in-repos/adding-features.md index 043bb83e9c..7509c2c27a 100644 --- a/Documentation/sourcebuild-in-repos/adding-features.md +++ b/Documentation/sourcebuild-in-repos/adding-features.md @@ -4,12 +4,14 @@ New features are great! They also have source-build considerations though. .NE ## Things to consider -New features, or expansions of current features, should act sensibly across Windows, Linux, and OSX. This also involves taking into account the limitations and conventions of the different platforms - for instance, on Linux, it's typical for the .NET SDK to be installed by root and therefore be unchangeable by normal users, so installing global tools needs to take into account the fact that the user might not be able to add anything to the SDK directories. +New features, or expansions of current features, should act sensibly across Windows, Linux, and OSX. This also involves taking into account the limitations and conventions of the different platforms - for instance, on Linux, it's typical for the .NET SDK to be installed by root and therefore be unchangeable by normal users, so installing global tools needs to take into account the fact that the user might not be able to add anything to the SDK directories (see https://github.com/dotnet/dotnet-docker/issues/520 and https://github.com/dotnet/installer/issues/7069). -XXX details on the global tools issues +New features also need to be compatible across all distributions of .NET - for instance, Fedora and Debian cannot distribute *any* non-open-source code, even samples, tests, or minor additions to licenses like restricting the field that the code can be used in. This includes any code or packages that are used to build product code as well. Microsoft generally prefers the MIT license. -New features also need to be compatible across all distributions of .NET - for instance, Fedora and Debian cannot distribute *any* non-open-source code, even samples, tests, or minor additions to licenses like restricting the field that the code can be used in. This includes any code or packages that are used to build product code as well. +One example of a licensing issue that source-build found was with dotnet-check and dotnet-format: these tools were brought into the product build but had a dependency that was not licensed compatibly - even without the source-build aspect. We had to scramble to replace the dependency before the release. Dependencies need to be carefully checked for license compatibility as well. -XXX fill in the details on dotnet-check/dotnet-format here +## Resources -XXX Should we create a Github group for source-build community members that would be interested in reviewing things like this? \ No newline at end of file +Fedora's approved open-source licenses can be found [on their wiki](https://fedoraproject.org/wiki/Licensing:Main#Good_Licenses), or you can check on the [OSI-approved list of licenses](https://opensource.org/licenses/alphabetical). + +If you would like some of our distribution maintainer partners to review your new feature you can ping @dotnet/distro-maintainers on a PR or issue. \ No newline at end of file diff --git a/Documentation/sourcebuild-in-repos/build-info.md b/Documentation/sourcebuild-in-repos/build-info.md index 17f3cdc75d..5d1f60a944 100644 --- a/Documentation/sourcebuild-in-repos/build-info.md +++ b/Documentation/sourcebuild-in-repos/build-info.md @@ -6,8 +6,12 @@ This is a collection of notes about how source-build can differ in general from Source-build is required to build on a single machine with no internet access. This means that we build targeting a single RID, usually the non-portable RID for the build machines (like rhel.7-x64). We do support building portable (linux-x64) as well - this is useful for bootstrapping new distributions. -We also only build one version of each repo. This means that if your repo turns production of some packages on and off, for instance, if you only produce packages if they are changed, source-build will need a workaround to force all packages to be produced. Additionally, we can only supply one version of each package to a repo. This is injected into the `$(PackageVersion)` variables. The exception is reference-only packages - dotnet/source-build-reference-packages produces multiple versions and these can be hard-coded or use a `$(ReferenceVersion)` property or similar if you don't need source-build to change them. +Source-build cannot build with any *prebuilts*. This is our term for any package that comes from *outside the current source-build*. This means that everything that ships out of source-build and everything that is used to build those shipping products must come from the source-build in progress. Packages from nuget.org, Microsoft builds, or other unrelated source-builds cannot be used in source-build except in a limited bootstrapping process. -## No Windows-specific packages +Source-build supplies a *previously-source-built* set of packages for this bootstrapping process. This is one way we have of breaking cycles in the build. However, none of these packages can make it to the final build output. This also means that your repo should be buildable with the immediately previous version of the SDK than you are building for; i.e., if you are building for 6.0.103, everything should be buildable with the 6.0.102 SDK. -Packages that require Windows components or references cannot be built in source-build. These should use `true` or other options to be excluded from the source-build. \ No newline at end of file +We also only build one version of each repo. This means that if your repo turns production of some packages on and off, for instance, if you only produce packages if they are changed, source-build will need a workaround to force all packages to be produced. Additionally, we can only supply one version of each package to a repo. This is injected into the `$(PackageVersion)` variables. One exception is reference-only packages - [dotnet/source-build-reference-packages](https://github.com/dotnet/source-build-reference-packages) produces multiple versions and these can be hard-coded or use a `$(ReferenceVersion)` property or similar if you don't need source-build to change them. + +## Platform-specific packages + +Packages that require components or packages only available on some other operating system than the building OS cannot be built in source-build. These should use `true` or other options to be excluded from the source-build. For instance, if a project depends on a package that can only be built on Windows, it will need to be disabled or worked around in source-build. As an example, [Roslyn removes](https://github.com/dotnet/roslyn/blob/b999a65c8b0feeccb2b58da3d7a6e80e5f08feab/src/Workspaces/Core/Portable/Storage/PersistentStorageExtensions.cs#L23) a small performance improvement when building for source-build because it requires a component that isn't available. \ No newline at end of file diff --git a/Documentation/sourcebuild-in-repos/new-dependencies.md b/Documentation/sourcebuild-in-repos/new-dependencies.md index bf20124ab3..fb1ad6a072 100644 --- a/Documentation/sourcebuild-in-repos/new-dependencies.md +++ b/Documentation/sourcebuild-in-repos/new-dependencies.md @@ -3,23 +3,30 @@ ## Basics When adding a new dependency, there are a few steps common between any type of dependency. If you use darc, `darc add-dependency` will take care of this process for you. Otherwise: 1. Add the package and a default version to eng/Versions.props. The default version property should be named `PackageVersion`, e.g. `SystemCollectionsImmutablePackageVersion`. -2. Add the package and a repo reference to eng/Version.Details.xml. +2. Add the package and a repo reference to eng/Version.Details.xml. This should include a SourceBuild metadata entry, looking something like: + ``` + https://github.com/dotnet/roslyn + 0167599e0e1634ea3ed8d0e41390a3c0d9b3e4e9 + + ``` 3. Set up dependency flow from the foreign repo to your repo. In general, you should aim to use one version of each package. If you are using a package as reference-only, it is possible to use multiple versions, but only one implementation version of each package will be used - source-build will override it to the version that is being built in this version of the SDK. ## Deciding what version to use -- If you are using the package as reference-only and want the version to be pinned, use a literal version number in the csprojs that reference the project. You can also set up a reference-only package version variable in eng/Versions.props, for instance `1.2.3` in addition to `4.5.6`. Also verify that the package is available in source-build-reference-packages, and if not, contact the source-build team. +- If you are using the package as reference-only and want the version to be pinned, use a literal version number in the csprojs that reference the project. You can also set up a reference-only package version variable in eng/Versions.props, for instance `1.2.3` in addition to `4.5.6`. Also verify that the package is available in [source-build-reference-packages](https://github.com/dotnet/source-build-reference-packages), and if not, contact the source-build team. - If you are using the package in the actual build or want the version to be updated whenever the foreign repo publishes to your channel, use the version number property set up in eng/Versions.props. This will be overridden in some cases by source-build. - If you are using an external or non-Arcade package, please coordinate as much as possible with other teams using that package. Each package-version is essentially maintained as a separate concern, so something like repo A requiring Newtonsoft.Json 9.0.1 and repo B requiring 12.0.2 essentially doubles the source-build team's work. ## Internal dependencies Adding a new dotnet dependency is usually pretty straightforward but does have some edge cases. Use this checklist: -1. Are you already using a package from the same repo? - 1. This is the simplest case. You can add new dependencies from repos you are already using freely. +1. Are you already using a package from the same repo and is the new dependency already source-built? + 1. This is the simplest case. You can add new dependencies from repos you are already using freely. Note that you need to use the same version for all packages from the repo. +2. Is the repo already built in source-build but the specific package is not? + 1. There's probably an issue with source-building this package. Please talk to a [source-build team member](https://github.com/orgs/dotnet/teams/source-build-internal) about why that is and whether we can fix it. 2. Is this a Microsoft repo that uses Arcade to build? 1. Does the foreign repo depend on your repo, directly or indirectly? i.e. would adding the dependency create a cycle? - 1. This isn't necessarily a deal-breaker - it can sometimes be worked around with reference-only packages. Please contact a source-build team member to discuss. + 1. This isn't necessarily a deal-breaker - it can sometimes be worked around with reference-only packages. Please contact a [source-build team member](https://github.com/orgs/dotnet/teams/source-build-internal) to discuss. 2. Does the foreign repo publish to BAR? 1. If not, please contact them to get them publishing to BAR in an appropriate channel. 3. If neither of these caveats apply you should be in good shape. Follow the instructions under "Basics" above. diff --git a/Documentation/sourcebuild-in-repos/update-dependencies.md b/Documentation/sourcebuild-in-repos/update-dependencies.md index 0b67ee41b1..e26d720db9 100644 --- a/Documentation/sourcebuild-in-repos/update-dependencies.md +++ b/Documentation/sourcebuild-in-repos/update-dependencies.md @@ -4,11 +4,16 @@ In most cases, dependency flow should automatically update the packages you depe ## External packages -Updating a non-Microsoft or non-Arcade package is typically equivalent to adding the new version all over again. Please contact a source-build team member to discuss this. +Updating a non-Microsoft (e.g. Newtonsoft.Json 9.0.1 to 13.0.1) or non-Arcade (e.g. ApplicationInsights) package is typically equivalent to adding the new version all over again. Please contact a [source-build team member](https://github.com/orgs/dotnet/teams/source-build-internal) to discuss this. ## Internal packages -If you are manually updating a package, please make sure it's from a compatible branch (e.g. runtime release/6.0 to sdk release/6.0.1xx, release/6.0.2xx, etc). Package versions that you are updating to should be source-built in their respective repos. If the version you need is produced in a branch that is not yet source-build-compatible please let the source-build team know. +If you are manually updating a package, please make sure it's from a compatible branch (e.g. runtime release/6.0 to sdk release/6.0.1xx, release/6.0.2xx, etc). Package versions that you are updating to should be source-built in their respective repos. If the version you need is produced in a branch that is not yet source-build-compatible please let the [source-build team](https://github.com/orgs/dotnet/teams/source-build-internal) know. + +Another common error we see is updating eng/Versions.props but not eng/Version.Details.xml. This causes problems for source-build because we depend on these files being updated in lockstep. Please prefer updating with Darc - it takes care of these issues - or, if a manual update really is necessary, make sure you update both files. + +An example Darc command could be +`darc update-dependencies --name MyCoolPackage -v 1.2.3` ## Splitting, combining, and moving packages @@ -16,7 +21,7 @@ These operations often end up causing source-build issues. A typical case of wh 1. Package A is produced in version 1. 2. In version 2, Package A is split into Package A1 and Package A2. 3. A downstream repo is never updated to take the split packages. -4. The version 2 source-build succeeds because Package A exists in the previously-source-built archive, but no new version of Package A is produced. +4. The version 2 source-build succeeds because Package A exists in the [previously-source-built archive](build-info.md#Single-version_and_single-RID_build), but no new version of Package A is produced. 5. Source-build version 3 fails because Package A no longer exists in the previously-source-built archive either. From eb294b49f2f97bf08399bf5c45d88299b0ce8726 Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Fri, 8 Apr 2022 12:54:06 -0500 Subject: [PATCH 10/16] Try to make this a bit clearer. --- Documentation/sourcebuild-in-repos/build-info.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/sourcebuild-in-repos/build-info.md b/Documentation/sourcebuild-in-repos/build-info.md index 5d1f60a944..ff292689e0 100644 --- a/Documentation/sourcebuild-in-repos/build-info.md +++ b/Documentation/sourcebuild-in-repos/build-info.md @@ -10,7 +10,7 @@ Source-build cannot build with any *prebuilts*. This is our term for any packag Source-build supplies a *previously-source-built* set of packages for this bootstrapping process. This is one way we have of breaking cycles in the build. However, none of these packages can make it to the final build output. This also means that your repo should be buildable with the immediately previous version of the SDK than you are building for; i.e., if you are building for 6.0.103, everything should be buildable with the 6.0.102 SDK. -We also only build one version of each repo. This means that if your repo turns production of some packages on and off, for instance, if you only produce packages if they are changed, source-build will need a workaround to force all packages to be produced. Additionally, we can only supply one version of each package to a repo. This is injected into the `$(PackageVersion)` variables. One exception is reference-only packages - [dotnet/source-build-reference-packages](https://github.com/dotnet/source-build-reference-packages) produces multiple versions and these can be hard-coded or use a `$(ReferenceVersion)` property or similar if you don't need source-build to change them. +We also only build one version of each repo. This means that if your repo turns production of some packages on and off, for instance, if you only produce packages if they are changed, source-build will need a workaround to force all packages to be produced. Additionally, we can only supply one version of each package to a repo. This is injected into the `$({PackageName}PackageVersion)` variables, e.g. SystemReflectionMetadataPackageVersion. One exception is reference-only packages - [dotnet/source-build-reference-packages](https://github.com/dotnet/source-build-reference-packages) produces multiple versions and these can be hard-coded or use a `$(ReferenceVersion)` property or similar if you don't need source-build to change them. ## Platform-specific packages From 93ba99824c48b999bdabd89417966e1838d5219f Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Wed, 20 Apr 2022 14:45:24 -0500 Subject: [PATCH 11/16] wip --- .../sourcebuild-in-repos/new-dependencies.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/Documentation/sourcebuild-in-repos/new-dependencies.md b/Documentation/sourcebuild-in-repos/new-dependencies.md index fb1ad6a072..4d389f80d7 100644 --- a/Documentation/sourcebuild-in-repos/new-dependencies.md +++ b/Documentation/sourcebuild-in-repos/new-dependencies.md @@ -13,15 +13,16 @@ When adding a new dependency, there are a few steps common between any type of d In general, you should aim to use one version of each package. If you are using a package as reference-only, it is possible to use multiple versions, but only one implementation version of each package will be used - source-build will override it to the version that is being built in this version of the SDK. -## Deciding what version to use -- If you are using the package as reference-only and want the version to be pinned, use a literal version number in the csprojs that reference the project. You can also set up a reference-only package version variable in eng/Versions.props, for instance `1.2.3` in addition to `4.5.6`. Also verify that the package is available in [source-build-reference-packages](https://github.com/dotnet/source-build-reference-packages), and if not, contact the source-build team. -- If you are using the package in the actual build or want the version to be updated whenever the foreign repo publishes to your channel, use the version number property set up in eng/Versions.props. This will be overridden in some cases by source-build. -- If you are using an external or non-Arcade package, please coordinate as much as possible with other teams using that package. Each package-version is essentially maintained as a separate concern, so something like repo A requiring Newtonsoft.Json 9.0.1 and repo B requiring 12.0.2 essentially doubles the source-build team's work. +The source-build metadata is important - this tells source-build which repo package contains the specific nupkg you want. A `` tag means that the dependency is needed both in the individual repo builds and the overall tarball build. A `` tag can be used for temporary issues when the required package is not included in the source-build intermediate package for that repo, or the source-build intermediate package is not produced. + +Another uncommon case that can cause problems is when the repo `` version and the source-built intermediate package version don't match. In this case, a direct dependency should be added to the source-build intermediate package and the CoherentParentDependency attribute should be set to the repo that consumes the dependency. For an example, see [installer's F# dependency](https://github.com/dotnet/installer/blob/ba1739a2363b1062f03ea386ec67174c6468d3b2/eng/Version.Details.xml#L128). You can find the version needed by running `darc get-build` or using [BAR](https://aka.ms/bar). ## Internal dependencies -Adding a new dotnet dependency is usually pretty straightforward but does have some edge cases. Use this checklist: +Internal dependencies are from Microsoft .NET repos. Adding a new dotnet dependency is usually pretty straightforward but does have some edge cases. Use this checklist: 1. Are you already using a package from the same repo and is the new dependency already source-built? 1. This is the simplest case. You can add new dependencies from repos you are already using freely. Note that you need to use the same version for all packages from the repo. +2. Is the repo already built in source-build including the specific package you want? + 1. Add the dependency using `darc add-dependency` as normal, then add the [source-build metadata](#Basics) as above. 2. Is the repo already built in source-build but the specific package is not? 1. There's probably an issue with source-building this package. Please talk to a [source-build team member](https://github.com/orgs/dotnet/teams/source-build-internal) about why that is and whether we can fix it. 2. Is this a Microsoft repo that uses Arcade to build? @@ -37,4 +38,9 @@ Adding a new dotnet dependency is usually pretty straightforward but does have s External (non-Microsoft or even non-dotnet) dependencies need to be carefully considered for source-build in addition to the licensing issues you are probably already familiar with. 1. Microsoft but non-dotnet repos should usually be able to use the same Arcade wrapper to publish appropriate packages for source-build - please contact a source-build team member to discuss. 2. Dependencies that have no code (e.g. SDKs with just props and targets) can usually be added using the source-build text-only-package process. Contact a source-build team member for more information. -3. We build some external dependencies in the dotnet/source-build repo. Good targets for this generally have very few if any dependencies and very simple build processes. Contact a source-build team member for more information. \ No newline at end of file +3. We build some external dependencies in the dotnet/source-build repo. Good targets for this generally have very few if any dependencies and very simple build processes. Contact a source-build team member for more information. + +## Deciding what version to use +- If you are using the package as reference-only and want the version to be pinned, use a literal version number in the csprojs that reference the project. You can also set up a reference-only package version variable in eng/Versions.props, for instance `1.2.3` in addition to `4.5.6`. Also verify that the package is available in [source-build-reference-packages](https://github.com/dotnet/source-build-reference-packages), and if not, [file a source-build issue](https://github.com/dotnet/source-build/issues). +- If you are using the package in the actual build or want the version to be updated whenever the foreign repo publishes to your channel, use the version number property set up in eng/Versions.props. When performing a source-build, the version number will get updated to the current source-built version. +- If you are using an external or non-Arcade package, please coordinate as much as possible with other teams using that package. Each package-version is essentially maintained as a separate concern, so something like repo A requiring Newtonsoft.Json 9.0.1 and repo B requiring 12.0.2 essentially doubles the source-build team's work. \ No newline at end of file From afbf2682658773401343d9b995fd318a67212fa1 Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Fri, 29 Apr 2022 11:40:03 -0500 Subject: [PATCH 12/16] Update for review comments. --- .../sourcebuild-in-repos/new-dependencies.md | 18 +++++++++--------- Documentation/sourcebuild-in-repos/new-repo.md | 2 +- .../update-dependencies.md | 12 ++++++------ 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Documentation/sourcebuild-in-repos/new-dependencies.md b/Documentation/sourcebuild-in-repos/new-dependencies.md index 4d389f80d7..3d9eb8fb74 100644 --- a/Documentation/sourcebuild-in-repos/new-dependencies.md +++ b/Documentation/sourcebuild-in-repos/new-dependencies.md @@ -17,28 +17,28 @@ The source-build metadata is important - this tells source-build which repo pack Another uncommon case that can cause problems is when the repo `` version and the source-built intermediate package version don't match. In this case, a direct dependency should be added to the source-build intermediate package and the CoherentParentDependency attribute should be set to the repo that consumes the dependency. For an example, see [installer's F# dependency](https://github.com/dotnet/installer/blob/ba1739a2363b1062f03ea386ec67174c6468d3b2/eng/Version.Details.xml#L128). You can find the version needed by running `darc get-build` or using [BAR](https://aka.ms/bar). -## Internal dependencies -Internal dependencies are from Microsoft .NET repos. Adding a new dotnet dependency is usually pretty straightforward but does have some edge cases. Use this checklist: -1. Are you already using a package from the same repo and is the new dependency already source-built? +## Microsoft dependencies + +.NET dependencies are from a Microsoft .NET project. Adding a new .NET dependency is usually quite easy, especially if the repo uses Arcade to build. Internal dependencies are from Microsoft repos but not .NET. Adding a new internal dependency is usually pretty straightforward but does have some edge cases. Use this checklist: +1. Are you already using a package from the same repo and is the new dependency already source-built? You can determine this by checking if the repo has a SourceBuild leg building, e.g. runtime's is `runtime-dev-innerloop (Build Linux x64 release SourceBuild)`. 1. This is the simplest case. You can add new dependencies from repos you are already using freely. Note that you need to use the same version for all packages from the repo. 2. Is the repo already built in source-build including the specific package you want? 1. Add the dependency using `darc add-dependency` as normal, then add the [source-build metadata](#Basics) as above. -2. Is the repo already built in source-build but the specific package is not? +3. Is the repo already built in source-build but the specific package is not? 1. There's probably an issue with source-building this package. Please talk to a [source-build team member](https://github.com/orgs/dotnet/teams/source-build-internal) about why that is and whether we can fix it. -2. Is this a Microsoft repo that uses Arcade to build? +4. Is this a Microsoft repo that uses Arcade to build? 1. Does the foreign repo depend on your repo, directly or indirectly? i.e. would adding the dependency create a cycle? 1. This isn't necessarily a deal-breaker - it can sometimes be worked around with reference-only packages. Please contact a [source-build team member](https://github.com/orgs/dotnet/teams/source-build-internal) to discuss. 2. Does the foreign repo publish to BAR? 1. If not, please contact them to get them publishing to BAR in an appropriate channel. 3. If neither of these caveats apply you should be in good shape. Follow the instructions under "Basics" above. -3. Source-build has in the past used Arcade shims to allow non-Arcade repos to build appropriate packages for source-build. Please contact the source-build team to determine if this is a workable approach for your foreign repo. +5. Source-build has in the past used Arcade shims to allow non-Arcade repos to build appropriate packages for source-build. Please contact the [source-build team](https://github.com/orgs/dotnet/teams/source-build-internal) to determine if this is a workable approach for your foreign repo. ## External dependencies External (non-Microsoft or even non-dotnet) dependencies need to be carefully considered for source-build in addition to the licensing issues you are probably already familiar with. -1. Microsoft but non-dotnet repos should usually be able to use the same Arcade wrapper to publish appropriate packages for source-build - please contact a source-build team member to discuss. -2. Dependencies that have no code (e.g. SDKs with just props and targets) can usually be added using the source-build text-only-package process. Contact a source-build team member for more information. -3. We build some external dependencies in the dotnet/source-build repo. Good targets for this generally have very few if any dependencies and very simple build processes. Contact a source-build team member for more information. +1. Dependencies that have no code (e.g. SDKs with just props and targets) can usually be added using the [source-build text-only-package process](https://github.com/dotnet/source-build-reference-packages/tree/main/src/textOnlyPackages/src). If the package is not already included there, you can [open a PR](https://github.com/dotnet/source-build-reference-packages/pulls) or [file an issue](https://github.com/dotnet/source-build/issues/new/choose) to include it. +2. We build some external dependencies in the [dotnet/source-build-externals](https://github.com/dotnet/source-build-externals) repo. Good targets for this generally have very few if any dependencies and very simple build processes. [Contact a source-build team member](https://github.com/orgs/dotnet/teams/source-build-internal) for more information. ## Deciding what version to use - If you are using the package as reference-only and want the version to be pinned, use a literal version number in the csprojs that reference the project. You can also set up a reference-only package version variable in eng/Versions.props, for instance `1.2.3` in addition to `4.5.6`. Also verify that the package is available in [source-build-reference-packages](https://github.com/dotnet/source-build-reference-packages), and if not, [file a source-build issue](https://github.com/dotnet/source-build/issues). diff --git a/Documentation/sourcebuild-in-repos/new-repo.md b/Documentation/sourcebuild-in-repos/new-repo.md index 7e5a70cf88..a0f85fd660 100644 --- a/Documentation/sourcebuild-in-repos/new-repo.md +++ b/Documentation/sourcebuild-in-repos/new-repo.md @@ -247,7 +247,7 @@ The graph defined by `eng/Version.Details.xml` defines what is included in sourc [dotnet/installer](https://github.com/dotnet/installer/blob/main/eng/Version.Details.xml). The .NET source build insfrastructure walks this graph and determines the full set of repos to build. Source build will only build one copy/commit of each repo (the first commit found in the dependency graph). Therefore, when adding a new repositories, a dependency must be created within the `eng/Version.Details.xml` graph. To do this, go to the repo which depends on the new repo and add a [new -source build dependency](#eng/Version.Details.xml) to the new source build repo. +source build dependency](#engversiondetailsxml) to the new source build repo. ## Validate diff --git a/Documentation/sourcebuild-in-repos/update-dependencies.md b/Documentation/sourcebuild-in-repos/update-dependencies.md index e26d720db9..57b1e61c0f 100644 --- a/Documentation/sourcebuild-in-repos/update-dependencies.md +++ b/Documentation/sourcebuild-in-repos/update-dependencies.md @@ -1,10 +1,6 @@ # Updating a dependency -In most cases, dependency flow should automatically update the packages you depend on. There are some special considerations and things to keep in mind when doing manual updates. - -## External packages - -Updating a non-Microsoft (e.g. Newtonsoft.Json 9.0.1 to 13.0.1) or non-Arcade (e.g. ApplicationInsights) package is typically equivalent to adding the new version all over again. Please contact a [source-build team member](https://github.com/orgs/dotnet/teams/source-build-internal) to discuss this. +In most cases, dependency flow should automatically update the packages you depend on. There are some special considerations and things to keep in mind when doing manual updates. If you are manually updating a version, also see [the doc on new dependencies](new-dependencies.md) for special considerations. ## Internal packages @@ -12,9 +8,13 @@ If you are manually updating a package, please make sure it's from a compatible Another common error we see is updating eng/Versions.props but not eng/Version.Details.xml. This causes problems for source-build because we depend on these files being updated in lockstep. Please prefer updating with Darc - it takes care of these issues - or, if a manual update really is necessary, make sure you update both files. -An example Darc command could be +Example Darc command: `darc update-dependencies --name MyCoolPackage -v 1.2.3` +## External packages + +Updating a non-Microsoft (e.g. Newtonsoft.Json 9.0.1 to 13.0.1) or non-Arcade (e.g. ApplicationInsights) package is typically equivalent to adding the new version all over again. Please [log an issue](https://github.com/dotnet/source-build/issues/new/choose) to discuss this. You can check if the external package you want is already included in source-build in the [source-build-externals](https://github.com/dotnet/source-build-externals) repo. + ## Splitting, combining, and moving packages These operations often end up causing source-build issues. A typical case of what can happen is From ac51d064adcbb2da84ce91f42873fecfa3e22a1e Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Tue, 3 May 2022 14:18:53 -0500 Subject: [PATCH 13/16] Apply suggestions from code review Co-authored-by: Michael Simons --- Documentation/sourcebuild-in-repos/build-info.md | 2 +- Documentation/sourcebuild-in-repos/new-repo.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/sourcebuild-in-repos/build-info.md b/Documentation/sourcebuild-in-repos/build-info.md index ff292689e0..090a1b0815 100644 --- a/Documentation/sourcebuild-in-repos/build-info.md +++ b/Documentation/sourcebuild-in-repos/build-info.md @@ -1,6 +1,6 @@ # Source-build build info -This is a collection of notes about how source-build can differ in general from your repo's build and what kind of issues that can create. +This is a collection of notes about how source-build can differ in general from your repo's build and what kind of issues that can create. ## Single-version and single-RID build diff --git a/Documentation/sourcebuild-in-repos/new-repo.md b/Documentation/sourcebuild-in-repos/new-repo.md index a0f85fd660..7f35457ef4 100644 --- a/Documentation/sourcebuild-in-repos/new-repo.md +++ b/Documentation/sourcebuild-in-repos/new-repo.md @@ -14,7 +14,7 @@ The source code for the build tasks that run for prebuilt validation and interme Configuring source build involves setting up files in `eng/` that determine the behavior of source build in the repo. -These changes are all needed before the inner source build will work: +These changes are all needed before source build will work: * [`eng/SourceBuild.props`](#engsourcebuildprops) - Basic properties, such as repo name. * [`eng/SourceBuildPrebuiltBaseline.xml`](#engsourcebuildprebuiltbaselinexml) - Allow prebuilts. Until prebuilt detection is enabled/enforced, we allow all @@ -58,7 +58,7 @@ MSBuild code that can change the way source build behaves. ``` -This defines which prebuilt NuGet packages are allowed to be used during thebuild. Initially, all package IDs and versions are permitted (`*/*`). +This defines which prebuilt NuGet packages are allowed to be used during the build. Initially, all package IDs and versions are permitted (`*/*`). The `*/*` glob means "any nupkg id, any version". It will be replaced with more specific rules at a later phase once the repo level prebuilt detection infrastructure is completed. The goal is to make it specific, so when a PR introduces an unexpected prebuilt, PR validation will fail and let us resolve @@ -251,6 +251,6 @@ source build dependency](#engversiondetailsxml) to the new source build repo. ## Validate -Once the downstream dependency(s) are added to the new repo and those changes flow into `dotnet/installer`, a complete .NET source tarball can be build. -This will validate that no prebuilts we added to the system and everything is functioning correctly. Please notify +Once the downstream dependency(s) are added to the new repo and those changes flow into `dotnet/installer`, a complete .NET source tarball can be built. +This will validate that no prebuilts were added to the system and everything is functioning correctly. Please notify [@source-build-internal](https://github.com/orgs/dotnet/teams/source-build-internal) to be on the lookout for the new repo and they will validate as necessary. From e2a8873fd1bf2b3e2ea1319b7c20618af3d7d8df Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Tue, 3 May 2022 15:23:24 -0500 Subject: [PATCH 14/16] Address review comments. --- .../sourcebuild-in-repos/new-dependencies.md | 6 ++--- .../sourcebuild-in-repos/new-repo.md | 22 ++++++++++++------- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Documentation/sourcebuild-in-repos/new-dependencies.md b/Documentation/sourcebuild-in-repos/new-dependencies.md index 3d9eb8fb74..cebdd02c0d 100644 --- a/Documentation/sourcebuild-in-repos/new-dependencies.md +++ b/Documentation/sourcebuild-in-repos/new-dependencies.md @@ -13,13 +13,13 @@ When adding a new dependency, there are a few steps common between any type of d In general, you should aim to use one version of each package. If you are using a package as reference-only, it is possible to use multiple versions, but only one implementation version of each package will be used - source-build will override it to the version that is being built in this version of the SDK. -The source-build metadata is important - this tells source-build which repo package contains the specific nupkg you want. A `` tag means that the dependency is needed both in the individual repo builds and the overall tarball build. A `` tag can be used for temporary issues when the required package is not included in the source-build intermediate package for that repo, or the source-build intermediate package is not produced. +The source-build metadata is important - this tells source-build which repo package contains the specific nupkg you want. Another uncommon case that can cause problems is when the repo `` version and the source-built intermediate package version don't match. In this case, a direct dependency should be added to the source-build intermediate package and the CoherentParentDependency attribute should be set to the repo that consumes the dependency. For an example, see [installer's F# dependency](https://github.com/dotnet/installer/blob/ba1739a2363b1062f03ea386ec67174c6468d3b2/eng/Version.Details.xml#L128). You can find the version needed by running `darc get-build` or using [BAR](https://aka.ms/bar). ## Microsoft dependencies -.NET dependencies are from a Microsoft .NET project. Adding a new .NET dependency is usually quite easy, especially if the repo uses Arcade to build. Internal dependencies are from Microsoft repos but not .NET. Adding a new internal dependency is usually pretty straightforward but does have some edge cases. Use this checklist: +.NET dependencies are from a Microsoft .NET project, like [dotnet/roslyn](https://github.com/dotnet/roslyn), [dotnet/runtime](https://github.com/dotnet/runtime), and [dotnet/fsharp](https://github.com/dotnet/fsharp). These repos use Arcade to build and publish. Adding a new .NET dependency is usually quite easy. Internal dependencies are from Microsoft repos but not .NET, like [Microsoft/msbuild](https://github.com/dotnet/msbuild), [NuGet/NuGet.Client](https://github.com/NuGet/NuGet.Client), and [Microsoft/ApplicationInsights](https://github.com/Microsoft/ApplicationInsights-dotnet) Adding a new internal dependency is usually pretty straightforward but does have some edge cases. Use this checklist: 1. Are you already using a package from the same repo and is the new dependency already source-built? You can determine this by checking if the repo has a SourceBuild leg building, e.g. runtime's is `runtime-dev-innerloop (Build Linux x64 release SourceBuild)`. 1. This is the simplest case. You can add new dependencies from repos you are already using freely. Note that you need to use the same version for all packages from the repo. 2. Is the repo already built in source-build including the specific package you want? @@ -38,7 +38,7 @@ Another uncommon case that can cause problems is when the repo `` ve External (non-Microsoft or even non-dotnet) dependencies need to be carefully considered for source-build in addition to the licensing issues you are probably already familiar with. 1. Dependencies that have no code (e.g. SDKs with just props and targets) can usually be added using the [source-build text-only-package process](https://github.com/dotnet/source-build-reference-packages/tree/main/src/textOnlyPackages/src). If the package is not already included there, you can [open a PR](https://github.com/dotnet/source-build-reference-packages/pulls) or [file an issue](https://github.com/dotnet/source-build/issues/new/choose) to include it. -2. We build some external dependencies in the [dotnet/source-build-externals](https://github.com/dotnet/source-build-externals) repo. Good targets for this generally have very few if any dependencies and very simple build processes. [Contact a source-build team member](https://github.com/orgs/dotnet/teams/source-build-internal) for more information. +2. We build some external dependencies in the [dotnet/source-build-externals](https://github.com/dotnet/source-build-externals) repo. Good targets for this generally have very few if any dependencies and very simple build processes. [Please log an issue](https://github.com/dotnet/source-build/issues/new/choose) to get the process started. ## Deciding what version to use - If you are using the package as reference-only and want the version to be pinned, use a literal version number in the csprojs that reference the project. You can also set up a reference-only package version variable in eng/Versions.props, for instance `1.2.3` in addition to `4.5.6`. Also verify that the package is available in [source-build-reference-packages](https://github.com/dotnet/source-build-reference-packages), and if not, [file a source-build issue](https://github.com/dotnet/source-build/issues). diff --git a/Documentation/sourcebuild-in-repos/new-repo.md b/Documentation/sourcebuild-in-repos/new-repo.md index 7f35457ef4..4037d29a63 100644 --- a/Documentation/sourcebuild-in-repos/new-repo.md +++ b/Documentation/sourcebuild-in-repos/new-repo.md @@ -1,9 +1,6 @@ # Adding a new repository to source build -This document describes the overall process of onboarding new repos onto arcade powered source build (ArPow). For more details about how the build executes, see -[dotnet/arcade/.../Microsoft.DotNet.Arcade.Sdk/tools/SourceBuild](https://github.com/dotnet/arcade/tree/master/src/Microsoft.DotNet.Arcade.Sdk/tools/SourceBuild). -The source code for the build tasks that run for prebuilt validation and intermediate nupkg dependency reading are maintained at -[dotnet/arcade/.../Microsoft.DotNet.SourceBuild](https://github.com/dotnet/arcade/tree/master/src/Microsoft.DotNet.SourceBuild). +This document describes the overall process of onboarding new repos onto arcade powered source build (ArPow). 1. [Source Build Configuration](#source-build-configuration) 1. [Setup CI](#setup-ci) @@ -19,7 +16,7 @@ These changes are all needed before source build will work: * [`eng/SourceBuild.props`](#engsourcebuildprops) - Basic properties, such as repo name. * [`eng/SourceBuildPrebuiltBaseline.xml`](#engsourcebuildprebuiltbaselinexml) - Allow prebuilts. Until prebuilt detection is enabled/enforced, we allow all prebuilts. -* [`eng/Version.Details.xml`](#engversiondetailsxml) - Already exists, but modifications are needed to pull dependencies from upstream intermediate nupkgs. +* [`eng/Version.Details.xml`](#engversiondetailsxml) - Already exists, but modifications are needed to pull dependencies from upstream [intermediate nupkgs](planning/arcade-powered-source-build/README.md#intermediate-nupkg-outputsinputs). See the following sections for details: @@ -84,7 +81,7 @@ the meat of the build: the "inner" build runs inside an `Exec` task. The inner b ### Excluding components -It is not always necessary or correct to include all repo components in source build because they introduce prebuilt that cannot be source built. +It is not always necessary or correct to include all repo components in source build. Components should be excluded if they are not required for the platform being source-built. Including them expands the source-build graph and may not be possible because of licensing. Examples include tests, Windows components (rmember source build currently only supports Linux and macOS), etc. To exlcude these components use the `DotNetBuildFromSource` msbuild property to conditionally exclude. @@ -113,10 +110,12 @@ Condition="'$(DotNetBuildFromSource)' != 'true'" Dependency changes may include adding `SourceBuild` to existing dependency elements, and adding a new `source-build-reference-packages` element. `SourceBuild` causes the source build targets in the Arcade SDK to download [intermediate nupkg]s from the upstream repo's official build, rather than using -prebuilt binaries to fulfill the dependencies. Note that `RepoName` is used to calculate the ID of the [intermediate nupkg]: the `Dependency` `Name` is +prebuilt binaries to fulfill the dependencies. Note that `RepoName` is used to calculate the ID of the [intermediate nupkg](planning/arcade-powered-source-build/README.md#intermediate-nupkg-outputsinputs): the `Dependency` `Name` is ignored by source build. -`ManagedOnly` determines whether a RID suffix is necessary on the [intermediate nupkg] ID. For example, running source build on `dotnet/installer` with +Building with the source-built versions of your dependencies also means that any upstream repos will have been built in a source-build context, including things projects that are excluded from the source-build. This can help you find issues where your source-build depends on an upstream component that isn't actually built in source-build. + +`ManagedOnly` determines whether a RID suffix is necessary on the [intermediate nupkg](planning/arcade-powered-source-build/README.md#intermediate-nupkg-outputsinputs) ID. For example, running source build on `dotnet/installer` with `linux-x64` with the above example configuration will restore: * `Microsoft.SourceBuild.Intermediate.runtime.linux-x64` @@ -254,3 +253,10 @@ source build dependency](#engversiondetailsxml) to the new source build repo. Once the downstream dependency(s) are added to the new repo and those changes flow into `dotnet/installer`, a complete .NET source tarball can be built. This will validate that no prebuilts were added to the system and everything is functioning correctly. Please notify [@source-build-internal](https://github.com/orgs/dotnet/teams/source-build-internal) to be on the lookout for the new repo and they will validate as necessary. + +# Additional resources + +- For more details about how the build executes, see +[Arcade's build tools](https://github.com/dotnet/arcade/tree/master/src/Microsoft.DotNet.Arcade.Sdk/tools/SourceBuild). +- The source code for the build tasks that run for prebuilt validation and intermediate nupkg dependency reading are maintained in +[Arcade](https://github.com/dotnet/arcade/tree/master/src/Microsoft.DotNet.SourceBuild) as well. \ No newline at end of file From d021e413893ef6a333b4b090898372f98533f6af Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Tue, 3 May 2022 16:12:20 -0500 Subject: [PATCH 15/16] Markdown linter clean. --- Documentation/sourcebuild-in-repos/README.md | 3 +- .../sourcebuild-in-repos/adding-features.md | 42 +++- .../sourcebuild-in-repos/build-info.md | 51 +++- .../sourcebuild-in-repos/new-dependencies.md | 140 ++++++++--- .../sourcebuild-in-repos/new-repo.md | 219 ++++++++++++------ .../update-dependencies.md | 49 +++- 6 files changed, 372 insertions(+), 132 deletions(-) diff --git a/Documentation/sourcebuild-in-repos/README.md b/Documentation/sourcebuild-in-repos/README.md index 0ba930196a..cd29555615 100644 --- a/Documentation/sourcebuild-in-repos/README.md +++ b/Documentation/sourcebuild-in-repos/README.md @@ -1,6 +1,7 @@ # Repo owner's handbook for source-build -These docs aim to be a collection of useful information for repo owners who work with and participate in source-build. +These docs aim to be a collection of useful information for repo owners who work +with and participate in source-build. ## Index diff --git a/Documentation/sourcebuild-in-repos/adding-features.md b/Documentation/sourcebuild-in-repos/adding-features.md index 7509c2c27a..ae98d3d7b0 100644 --- a/Documentation/sourcebuild-in-repos/adding-features.md +++ b/Documentation/sourcebuild-in-repos/adding-features.md @@ -1,17 +1,43 @@ # New features -New features are great! They also have source-build considerations though. .NET is no longer just multi-platform but also multi-distribution: there's a Linux SDK produced by Microsoft, but there's also a Linux SDK produced by Red Hat, one produced by Fedora, and one that anyone in the community can build himself from source. +New features are great! They also have source-build considerations though. +.NET is no longer just multi-platform but also multi-distribution: there's +a Linux SDK produced by Microsoft, but there's also a Linux SDK produced +by Red Hat, one produced by Fedora, and one that anyone in the community +can build himself from source. ## Things to consider -New features, or expansions of current features, should act sensibly across Windows, Linux, and OSX. This also involves taking into account the limitations and conventions of the different platforms - for instance, on Linux, it's typical for the .NET SDK to be installed by root and therefore be unchangeable by normal users, so installing global tools needs to take into account the fact that the user might not be able to add anything to the SDK directories (see https://github.com/dotnet/dotnet-docker/issues/520 and https://github.com/dotnet/installer/issues/7069). - -New features also need to be compatible across all distributions of .NET - for instance, Fedora and Debian cannot distribute *any* non-open-source code, even samples, tests, or minor additions to licenses like restricting the field that the code can be used in. This includes any code or packages that are used to build product code as well. Microsoft generally prefers the MIT license. - -One example of a licensing issue that source-build found was with dotnet-check and dotnet-format: these tools were brought into the product build but had a dependency that was not licensed compatibly - even without the source-build aspect. We had to scramble to replace the dependency before the release. Dependencies need to be carefully checked for license compatibility as well. +New features, or expansions of current features, should act sensibly +across Windows, Linux, and OSX. This also involves taking into account +the limitations and conventions of the different platforms - for instance, +on Linux, it's typical for the .NET SDK to be installed by root and +therefore be unchangeable by normal users, so installing global tools +needs to take into account the fact that the user might not be able to +add anything to the SDK directories (see +[this docker global tools issue](https://github.com/dotnet/dotnet-docker/issues/520) +and [a similar installer issue](https://github.com/dotnet/installer/issues/7069)). + +New features also need to be compatible across all distributions of +.NET - for instance, Fedora and Debian cannot distribute *any* +non-open-source code, even samples, tests, or minor additions to +licenses like restricting the field that the code can be used in. +This includes any code or packages that are used to build product +code as well. Microsoft generally prefers the MIT license. + +One example of a licensing issue that source-build found was with +dotnet-check and dotnet-format: these tools were brought into the +product build but had a dependency that was not licensed compatibly - +even without the source-build aspect. We had to scramble to replace +the dependency before the release. Dependencies need to be carefully +checked for license compatibility as well. ## Resources -Fedora's approved open-source licenses can be found [on their wiki](https://fedoraproject.org/wiki/Licensing:Main#Good_Licenses), or you can check on the [OSI-approved list of licenses](https://opensource.org/licenses/alphabetical). +Fedora's approved open-source licenses can be found +[on their wiki](https://fedoraproject.org/wiki/Licensing:Main#Good_Licenses), +or you can check on the [OSI-approved list of licenses](https://opensource.org/licenses/alphabetical). -If you would like some of our distribution maintainer partners to review your new feature you can ping @dotnet/distro-maintainers on a PR or issue. \ No newline at end of file +If you would like some of our distribution maintainer partners to +review your new feature you can ping @dotnet/distro-maintainers +on a PR or issue. \ No newline at end of file diff --git a/Documentation/sourcebuild-in-repos/build-info.md b/Documentation/sourcebuild-in-repos/build-info.md index 090a1b0815..32d474842c 100644 --- a/Documentation/sourcebuild-in-repos/build-info.md +++ b/Documentation/sourcebuild-in-repos/build-info.md @@ -1,17 +1,50 @@ # Source-build build info -This is a collection of notes about how source-build can differ in general from your repo's build and what kind of issues that can create. +This is a collection of notes about how source-build can differ in general +from your repo's build and what kind of issues that can create. ## Single-version and single-RID build -Source-build is required to build on a single machine with no internet access. This means that we build targeting a single RID, usually the non-portable RID for the build machines (like rhel.7-x64). We do support building portable (linux-x64) as well - this is useful for bootstrapping new distributions. - -Source-build cannot build with any *prebuilts*. This is our term for any package that comes from *outside the current source-build*. This means that everything that ships out of source-build and everything that is used to build those shipping products must come from the source-build in progress. Packages from nuget.org, Microsoft builds, or other unrelated source-builds cannot be used in source-build except in a limited bootstrapping process. - -Source-build supplies a *previously-source-built* set of packages for this bootstrapping process. This is one way we have of breaking cycles in the build. However, none of these packages can make it to the final build output. This also means that your repo should be buildable with the immediately previous version of the SDK than you are building for; i.e., if you are building for 6.0.103, everything should be buildable with the 6.0.102 SDK. - -We also only build one version of each repo. This means that if your repo turns production of some packages on and off, for instance, if you only produce packages if they are changed, source-build will need a workaround to force all packages to be produced. Additionally, we can only supply one version of each package to a repo. This is injected into the `$({PackageName}PackageVersion)` variables, e.g. SystemReflectionMetadataPackageVersion. One exception is reference-only packages - [dotnet/source-build-reference-packages](https://github.com/dotnet/source-build-reference-packages) produces multiple versions and these can be hard-coded or use a `$(ReferenceVersion)` property or similar if you don't need source-build to change them. +Source-build is required to build on a single machine with no internet +access. This means that we build targeting a single RID, usually the +non-portable RID for the build machines (like rhel.7-x64). We do +support building portable (linux-x64) as well - this is useful for +bootstrapping new distributions. + +Source-build cannot build with any *prebuilts*. This is our term for +any package that comes from *outside the current source-build*. This means +that everything that ships out of source-build and everything that is used to +build those shipping products must come from the source-build in progress. +Packages from nuget.org, Microsoft builds, or other unrelated source-builds +cannot be used in source-build except in a limited bootstrapping process. + +Source-build supplies a *previously-source-built* set of packages for this +bootstrapping process. This is one way we have of breaking cycles in the +build. However, none of these packages can make it to the final build output. +This also means that your repo should be buildable with the immediately +previous version of the SDK than you are building for; i.e., if you are +building for 6.0.103, everything should be buildable with the 6.0.102 SDK. + +We also only build one version of each repo. This means that if your repo +turns production of some packages on and off, for instance, if you only +produce packages if they are changed, source-build will need a workaround +to force all packages to be produced. Additionally, we can only supply +one version of each package to a repo. This is injected into the +`$({PackageName}PackageVersion)` variables, e.g. SystemReflectionMetadataPackageVersion. +One exception is reference-only packages - +[dotnet/source-build-reference-packages](https://github.com/dotnet/source-build-reference-packages) +produces multiple versions and these can be hard-coded or use a +`$(ReferenceVersion)` property or similar if you don't +need source-build to change them. ## Platform-specific packages -Packages that require components or packages only available on some other operating system than the building OS cannot be built in source-build. These should use `true` or other options to be excluded from the source-build. For instance, if a project depends on a package that can only be built on Windows, it will need to be disabled or worked around in source-build. As an example, [Roslyn removes](https://github.com/dotnet/roslyn/blob/b999a65c8b0feeccb2b58da3d7a6e80e5f08feab/src/Workspaces/Core/Portable/Storage/PersistentStorageExtensions.cs#L23) a small performance improvement when building for source-build because it requires a component that isn't available. \ No newline at end of file +Packages that require components or packages only available on some other +operating system than the building OS cannot be built in source-build. +These should use `true` or +other options to be excluded from the source-build. For instance, if a +project depends on a package that can only be built on Windows, it will need +to be disabled or worked around in source-build. As an example, +[Roslyn removes](https://github.com/dotnet/roslyn/blob/b999a65c8b0feeccb2b58da3d7a6e80e5f08feab/src/Workspaces/Core/Portable/Storage/PersistentStorageExtensions.cs#L23) +a small performance improvement when building for source-build because it +requires a component that isn't available. \ No newline at end of file diff --git a/Documentation/sourcebuild-in-repos/new-dependencies.md b/Documentation/sourcebuild-in-repos/new-dependencies.md index cebdd02c0d..e72d4ccebc 100644 --- a/Documentation/sourcebuild-in-repos/new-dependencies.md +++ b/Documentation/sourcebuild-in-repos/new-dependencies.md @@ -1,46 +1,128 @@ # Adding a new dependency ## Basics -When adding a new dependency, there are a few steps common between any type of dependency. If you use darc, `darc add-dependency` will take care of this process for you. Otherwise: -1. Add the package and a default version to eng/Versions.props. The default version property should be named `PackageVersion`, e.g. `SystemCollectionsImmutablePackageVersion`. -2. Add the package and a repo reference to eng/Version.Details.xml. This should include a SourceBuild metadata entry, looking something like: - ``` + +When adding a new dependency, there are a few steps common between any type +of dependency. If you use darc, `darc add-dependency` will take care of +this process for you. Otherwise: + +1. Add the package and a default version to eng/Versions.props. The default + version property should be named `PackageVersion`, + e.g. `SystemCollectionsImmutablePackageVersion`. +1. Add the package and a repo reference to eng/Version.Details.xml. This + should include a SourceBuild metadata entry, looking something like: + +```xml + https://github.com/dotnet/roslyn 0167599e0e1634ea3ed8d0e41390a3c0d9b3e4e9 - ``` -3. Set up dependency flow from the foreign repo to your repo. + +``` + +1. Set up dependency flow from the foreign repo to your repo. -In general, you should aim to use one version of each package. If you are using a package as reference-only, it is possible to use multiple versions, but only one implementation version of each package will be used - source-build will override it to the version that is being built in this version of the SDK. +In general, you should aim to use one version of each package. If you are +using a package as reference-only, it is possible to use multiple versions, +but only one implementation version of each package will be used - +source-build will override it to the version that is being built in this +version of the SDK. -The source-build metadata is important - this tells source-build which repo package contains the specific nupkg you want. +The source-build metadata is important - this tells source-build which repo +package contains the specific nupkg you want. -Another uncommon case that can cause problems is when the repo `` version and the source-built intermediate package version don't match. In this case, a direct dependency should be added to the source-build intermediate package and the CoherentParentDependency attribute should be set to the repo that consumes the dependency. For an example, see [installer's F# dependency](https://github.com/dotnet/installer/blob/ba1739a2363b1062f03ea386ec67174c6468d3b2/eng/Version.Details.xml#L128). You can find the version needed by running `darc get-build` or using [BAR](https://aka.ms/bar). +Another uncommon case that can cause problems is when the repo `` +version and the source-built intermediate package version don't match. +In this case, a direct dependency should be added to the source-build +intermediate package and the CoherentParentDependency attribute should be +set to the repo that consumes the dependency. For an example, +see [installer's F# dependency](https://github.com/dotnet/installer/blob/ba1739a2363b1062f03ea386ec67174c6468d3b2/eng/Version.Details.xml#L128). +You can find the version needed by running `darc get-build` +or using [BAR](https://aka.ms/bar). ## Microsoft dependencies -.NET dependencies are from a Microsoft .NET project, like [dotnet/roslyn](https://github.com/dotnet/roslyn), [dotnet/runtime](https://github.com/dotnet/runtime), and [dotnet/fsharp](https://github.com/dotnet/fsharp). These repos use Arcade to build and publish. Adding a new .NET dependency is usually quite easy. Internal dependencies are from Microsoft repos but not .NET, like [Microsoft/msbuild](https://github.com/dotnet/msbuild), [NuGet/NuGet.Client](https://github.com/NuGet/NuGet.Client), and [Microsoft/ApplicationInsights](https://github.com/Microsoft/ApplicationInsights-dotnet) Adding a new internal dependency is usually pretty straightforward but does have some edge cases. Use this checklist: -1. Are you already using a package from the same repo and is the new dependency already source-built? You can determine this by checking if the repo has a SourceBuild leg building, e.g. runtime's is `runtime-dev-innerloop (Build Linux x64 release SourceBuild)`. - 1. This is the simplest case. You can add new dependencies from repos you are already using freely. Note that you need to use the same version for all packages from the repo. -2. Is the repo already built in source-build including the specific package you want? - 1. Add the dependency using `darc add-dependency` as normal, then add the [source-build metadata](#Basics) as above. -3. Is the repo already built in source-build but the specific package is not? - 1. There's probably an issue with source-building this package. Please talk to a [source-build team member](https://github.com/orgs/dotnet/teams/source-build-internal) about why that is and whether we can fix it. -4. Is this a Microsoft repo that uses Arcade to build? - 1. Does the foreign repo depend on your repo, directly or indirectly? i.e. would adding the dependency create a cycle? - 1. This isn't necessarily a deal-breaker - it can sometimes be worked around with reference-only packages. Please contact a [source-build team member](https://github.com/orgs/dotnet/teams/source-build-internal) to discuss. - 2. Does the foreign repo publish to BAR? - 1. If not, please contact them to get them publishing to BAR in an appropriate channel. - 3. If neither of these caveats apply you should be in good shape. Follow the instructions under "Basics" above. -5. Source-build has in the past used Arcade shims to allow non-Arcade repos to build appropriate packages for source-build. Please contact the [source-build team](https://github.com/orgs/dotnet/teams/source-build-internal) to determine if this is a workable approach for your foreign repo. +.NET dependencies are from a Microsoft .NET project, like +[dotnet/roslyn](https://github.com/dotnet/roslyn), +[dotnet/runtime](https://github.com/dotnet/runtime), +and [dotnet/fsharp](https://github.com/dotnet/fsharp). These repos use +Arcade to build and publish. Adding a new .NET dependency is usually +quite easy. Internal dependencies are from Microsoft repos but not .NET, +like [Microsoft/msbuild](https://github.com/dotnet/msbuild), +[NuGet/NuGet.Client](https://github.com/NuGet/NuGet.Client), +and [Microsoft/ApplicationInsights](https://github.com/Microsoft/ApplicationInsights-dotnet). +Adding a new internal dependency is usually pretty straightforward but does +have some edge cases. Use this checklist: + +1. Are you already using a package from the same repo and is the new + dependency already source-built? You can determine this by checking if + the repo has a SourceBuild leg building, e.g. runtime's is + `runtime-dev-innerloop (Build Linux x64 release SourceBuild)`. + + 1. This is the simplest case. You can add new dependencies from repos + you are already using freely. Note that you need to use the same version + for all packages from the repo. +1. Is the repo already built in source-build including the specific + package you want? + 1. Add the dependency using `darc add-dependency` as normal, then + add the [source-build metadata](#Basics) as above. +1. Is the repo already built in source-build but the specific package is not? + 1. There's probably an issue with source-building this package. Please + talk to a [source-build team member](https://github.com/orgs/dotnet/teams/source-build-internal) + about why that is and whether we can fix it. +1. Is this a Microsoft repo that uses Arcade to build? + 1. Does the foreign repo depend on your repo, directly or indirectly? + i.e. would adding the dependency create a cycle? + 1. This isn't necessarily a deal-breaker - it can sometimes be worked + around with reference-only packages. Please contact a + [source-build team member](https://github.com/orgs/dotnet/teams/source-build-internal) + to discuss. + 1. Does the foreign repo publish to BAR? + 1. If not, please contact them to get them publishing to BAR + in an appropriate channel. + 1. If neither of these caveats apply you should be in good shape. + Follow the instructions under "Basics" above. +1. Source-build has in the past used Arcade shims to allow non-Arcade repos + to build appropriate packages for source-build. Please contact the + [source-build team](https://github.com/orgs/dotnet/teams/source-build-internal) + to determine if this is a workable approach for your foreign repo. ## External dependencies -External (non-Microsoft or even non-dotnet) dependencies need to be carefully considered for source-build in addition to the licensing issues you are probably already familiar with. -1. Dependencies that have no code (e.g. SDKs with just props and targets) can usually be added using the [source-build text-only-package process](https://github.com/dotnet/source-build-reference-packages/tree/main/src/textOnlyPackages/src). If the package is not already included there, you can [open a PR](https://github.com/dotnet/source-build-reference-packages/pulls) or [file an issue](https://github.com/dotnet/source-build/issues/new/choose) to include it. -2. We build some external dependencies in the [dotnet/source-build-externals](https://github.com/dotnet/source-build-externals) repo. Good targets for this generally have very few if any dependencies and very simple build processes. [Please log an issue](https://github.com/dotnet/source-build/issues/new/choose) to get the process started. +External (non-Microsoft or even non-dotnet) dependencies need to be carefully +considered for source-build in addition to the licensing issues you are +probably already familiar with. + +1. Dependencies that have no code (e.g. SDKs with just props and targets) can + usually be added using the [source-build text-only-package process](https://github.com/dotnet/source-build-reference-packages/tree/main/src/textOnlyPackages/src). + If the package is not already included there, you can [open a PR](https://github.com/dotnet/source-build-reference-packages/pulls) + or [file an issue](https://github.com/dotnet/source-build/issues/new/choose) + to include it. +1. We build some external dependencies in the [dotnet/source-build-externals](https://github.com/dotnet/source-build-externals) + repo. Good targets for this generally have very few if any dependencies and + very simple build processes. + [Please log an issue](https://github.com/dotnet/source-build/issues/new/choose) + to get the process started. ## Deciding what version to use -- If you are using the package as reference-only and want the version to be pinned, use a literal version number in the csprojs that reference the project. You can also set up a reference-only package version variable in eng/Versions.props, for instance `1.2.3` in addition to `4.5.6`. Also verify that the package is available in [source-build-reference-packages](https://github.com/dotnet/source-build-reference-packages), and if not, [file a source-build issue](https://github.com/dotnet/source-build/issues). -- If you are using the package in the actual build or want the version to be updated whenever the foreign repo publishes to your channel, use the version number property set up in eng/Versions.props. When performing a source-build, the version number will get updated to the current source-built version. -- If you are using an external or non-Arcade package, please coordinate as much as possible with other teams using that package. Each package-version is essentially maintained as a separate concern, so something like repo A requiring Newtonsoft.Json 9.0.1 and repo B requiring 12.0.2 essentially doubles the source-build team's work. \ No newline at end of file + +- If you are using the package as reference-only and want the version to be + pinned, use a literal version number in the csprojs that reference the + project. You can also set up a reference-only package version variable + in eng/Versions.props, for instance `1.2.3` + in addition to `4.5.6`. + Also verify that the package is available in + [source-build-reference-packages](https://github.com/dotnet/source-build-reference-packages), + and if not, [file a source-build issue](https://github.com/dotnet/source-build/issues). +- If you are using the package in the actual build or want the version + to be updated whenever the foreign repo publishes to your channel, use + the version number property set up in eng/Versions.props. When performing + a source-build, the version number will get updated to the current + source-built version. +- If you are using an external or non-Arcade package, please coordinate as + much as possible with other teams using that package. Each + package-version is essentially maintained as a separate concern, so + something like repo A requiring Newtonsoft.Json 9.0.1 and repo B requiring + 12.0.2 essentially doubles the source-build team's work. \ No newline at end of file diff --git a/Documentation/sourcebuild-in-repos/new-repo.md b/Documentation/sourcebuild-in-repos/new-repo.md index 4037d29a63..2189f59690 100644 --- a/Documentation/sourcebuild-in-repos/new-repo.md +++ b/Documentation/sourcebuild-in-repos/new-repo.md @@ -1,6 +1,7 @@ # Adding a new repository to source build -This document describes the overall process of onboarding new repos onto arcade powered source build (ArPow). +This document describes the overall process of onboarding new repos onto +arcade powered source build (ArPow). 1. [Source Build Configuration](#source-build-configuration) 1. [Setup CI](#setup-ci) @@ -9,14 +10,19 @@ This document describes the overall process of onboarding new repos onto arcade ## Source Build Configuration -Configuring source build involves setting up files in `eng/` that determine the behavior of source build in the repo. +Configuring source build involves setting up files in `eng/` that +determine the behavior of source build in the repo. These changes are all needed before source build will work: -* [`eng/SourceBuild.props`](#engsourcebuildprops) - Basic properties, such as repo name. -* [`eng/SourceBuildPrebuiltBaseline.xml`](#engsourcebuildprebuiltbaselinexml) - Allow prebuilts. Until prebuilt detection is enabled/enforced, we allow all +* [`eng/SourceBuild.props`](#engsourcebuildprops) - + Basic properties, such as repo name. +* [`eng/SourceBuildPrebuiltBaseline.xml`](#engsourcebuildprebuiltbaselinexml) - + Allow prebuilts. Until prebuilt detection is enabled/enforced, we allow all prebuilts. -* [`eng/Version.Details.xml`](#engversiondetailsxml) - Already exists, but modifications are needed to pull dependencies from upstream [intermediate nupkgs](planning/arcade-powered-source-build/README.md#intermediate-nupkg-outputsinputs). +* [`eng/Version.Details.xml`](#engversiondetailsxml) - + Already exists, but modifications are needed to pull dependencies from + upstream [intermediate nupkgs](planning/arcade-powered-source-build/README.md#intermediate-nupkg-outputsinputs). See the following sections for details: @@ -33,16 +39,21 @@ See the following sections for details: ``` -This file contains basic configuration used to restore the correct dependencies (managed-only or not) and produce the right name for the repo's [intermediate -nupkg]. +This file contains basic configuration used to restore the correct +dependencies (managed-only or not) and produce the right name for +the repo's [intermediate nupkg]. -* `this-repo` should be the same as the repo's name on GitHub, without the GitHub organization name. -* `SourceBuildManagedOnly` defaults to false if omitted. `true` means that the repo doesn't produce any RID-specific artifacts like +* `this-repo` should be the same as the repo's name on GitHub, + without the GitHub organization name. +* `SourceBuildManagedOnly` defaults to false if omitted. `true` means + that the repo doesn't produce any RID-specific artifacts like `Microsoft.NETCore.App.Runtime.linux-x64`, only managed code. -These two properties determine the name of the [intermediate nupkg]: `Microsoft.SourceBuild.Intermediate.$(GitHubRepositoryName)[.$(RidSuffix)]`. +These two properties determine the name of the [intermediate nupkg]: +`Microsoft.SourceBuild.Intermediate.$(GitHubRepositoryName)[.$(RidSuffix)]`. -It's possible more configuration will be required for specific repos. `eng/SourceBuild.props`, similar to `eng/Build.props`, is a place to add extra +It's possible more configuration will be required for specific repos. +`eng/SourceBuild.props`, similar to `eng/Build.props`, is a place to add extra MSBuild code that can change the way source build behaves. ### `eng/SourceBuildPrebuiltBaseline.xml` @@ -55,34 +66,45 @@ MSBuild code that can change the way source build behaves. ``` -This defines which prebuilt NuGet packages are allowed to be used during the build. Initially, all package IDs and versions are permitted (`*/*`). +This defines which prebuilt NuGet packages are allowed to be used during +the build. Initially, all package IDs and versions are permitted (`*/*`). -The `*/*` glob means "any nupkg id, any version". It will be replaced with more specific rules at a later phase once the repo level prebuilt detection -infrastructure is completed. The goal is to make it specific, so when a PR introduces an unexpected prebuilt, PR validation will fail and let us resolve +The `*/*` glob means "any nupkg id, any version". It will be replaced with +more specific rules at a later phase once the repo level prebuilt detection +infrastructure is completed. The goal is to make it specific, so when a PR +introduces an unexpected prebuilt, PR validation will fail and let us resolve the source-buildability issue before the PR gets merged. ### Trying it out locally -After setting up ArPow in a repo, running it locally is done by passing `/p:ArcadeBuildFromSource=true` at the end of the usual -arcade-based build command for the repo. For example: +After setting up ArPow in a repo, running it locally is done by passing +`/p:ArcadeBuildFromSource=true` at the end of the usual arcade-based build +command for the repo. For example: ```bash ./build.sh -c Release --restore --build --pack /p:ArcadeBuildFromSource=true -bl ``` -> Note: [source build is not supported on Windows](https://github.com/dotnet/source-build/issues/1190), only Linux and macOS. +> Note: [source build is not supported on Windows](https://github.com/dotnet/source-build/issues/1190), +only Linux and macOS. -After running the build, source build artifacts will be in `artifacts/source-build`, and the [intermediate nupkg] will be something like +After running the build, source build artifacts will be in `artifacts/source-build`, +and the [intermediate nupkg] will be something like `artifacts/packages/*/Microsoft.SourceBuild.Intermediate.*.nupkg`. -The MSBuild binlog will be placed somewhere like: `artifacts/log/Debug/Build.binlog`. However, this "outer" binlog doesn't contain -the meat of the build: the "inner" build runs inside an `Exec` task. The inner binlog will be written to: +The MSBuild binlog will be placed somewhere like: `artifacts/log/Debug/Build.binlog`. +However, this "outer" binlog doesn't contain the meat of the build: the +"inner" build runs inside an `Exec` task. The inner binlog will be written to: `artifacts/source-build/self/src/artifacts/sourcebuild.binlog`. ### Excluding components -It is not always necessary or correct to include all repo components in source build. Components should be excluded if they are not required for the platform being source-built. Including them expands the source-build graph and may not be possible because of licensing. -Examples include tests, Windows components (rmember source build currently only supports Linux and macOS), etc. To exlcude these components +It is not always necessary or correct to include all repo components in +source build. Components should be excluded if they are not required for +the platform being source-built. Including them expands the source-build +graph and may not be possible because of licensing. +Examples include tests, Windows components (rmember source build currently +only supports Linux and macOS), etc. To exlcude these components use the `DotNetBuildFromSource` msbuild property to conditionally exclude. ```code @@ -93,29 +115,42 @@ Condition="'$(DotNetBuildFromSource)' != 'true'" ```xml ... - + https://github.com/dotnet/runtime a820ca1c4f9cb5892331e2624d3999c39161fe2a ... - + https://github.com/dotnet/source-build-reference-packages def2e2c6dc5064319250e2868a041a3dc07f9579 - + ... ``` -Dependency changes may include adding `SourceBuild` to existing dependency elements, and adding a new `source-build-reference-packages` element. - -`SourceBuild` causes the source build targets in the Arcade SDK to download [intermediate nupkg]s from the upstream repo's official build, rather than using -prebuilt binaries to fulfill the dependencies. Note that `RepoName` is used to calculate the ID of the [intermediate nupkg](planning/arcade-powered-source-build/README.md#intermediate-nupkg-outputsinputs): the `Dependency` `Name` is -ignored by source build. - -Building with the source-built versions of your dependencies also means that any upstream repos will have been built in a source-build context, including things projects that are excluded from the source-build. This can help you find issues where your source-build depends on an upstream component that isn't actually built in source-build. - -`ManagedOnly` determines whether a RID suffix is necessary on the [intermediate nupkg](planning/arcade-powered-source-build/README.md#intermediate-nupkg-outputsinputs) ID. For example, running source build on `dotnet/installer` with +Dependency changes may include adding `SourceBuild` to existing dependency +elements, and adding a new `source-build-reference-packages` element. + +`SourceBuild` causes the source build targets in the Arcade SDK to download +[intermediate nupkg]s from the upstream repo's official build, rather than +using prebuilt binaries to fulfill the dependencies. Note that `RepoName` +is used to calculate the ID of the +[intermediate nupkg](planning/arcade-powered-source-build/README.md#intermediate-nupkg-outputsinputs): +the `Dependency` `Name` is ignored by source build. + +Building with the source-built versions of your dependencies also means that +any upstream repos will have been built in a source-build context, including +things projects that are excluded from the source-build. This can help you +find issues where your source-build depends on an upstream component that +isn't actually built in source-build. + +`ManagedOnly` determines whether a RID suffix is necessary on the +[intermediate nupkg](planning/arcade-powered-source-build/README.md#intermediate-nupkg-outputsinputs) +ID. For example, running source build on `dotnet/installer` with `linux-x64` with the above example configuration will restore: * `Microsoft.SourceBuild.Intermediate.runtime.linux-x64` @@ -125,18 +160,25 @@ Building with the source-built versions of your dependencies also means that any ## Setup CI -ArPow needs to run during official builds to create source build [intermediate nupkg]s for the downstream repos that will -consume them. ArPow should also run in PR validation builds, to prevent regression in the ArPow flow. +ArPow needs to run during official builds to create source build +[intermediate nupkg]s for the downstream repos that will consume them. +ArPow should also run in PR validation builds, to prevent regression +in the ArPow flow. -The ArPow implementation can be activated with a single flag in the ordinary Arcade SDK jobs template for easy consumption. If a repo can't simply use the -Arcade SDK jobs template, more granular templates are also available. +The ArPow implementation can be activated with a single flag in the +ordinary Arcade SDK jobs template for easy consumption. If a repo can't +simply use the Arcade SDK jobs template, more granular templates are +also available. -See for the current template source code. The inline comments in the `parameters:` section -in those files are the most up to date docs, maintained with higher priority than this general onboarding doc. +See +for the current template source code. The inline comments in the +`parameters:` section in those files are the most up to date docs, maintained +with higher priority than this general onboarding doc. ### `eng/common/templates/jobs/jobs.yml` opt-in switch -The simplest way to onboard. This approach applies if the repo already uses the `eng/common/templates/jobs/jobs.yml` template. +The simplest way to onboard. This approach applies if the repo already +uses the `eng/common/templates/jobs/jobs.yml` template. To opt in: @@ -165,8 +207,10 @@ To opt in: 1. Specify platforms (if repo is not managed-only) - A repo is managed-only if `eng/SourceBuild.props` contains `true`. If this is true, this - step is not necessary. Otherwise, specify `sourceBuildParameters` in the `jobs.yml` template's parameters like this: + A repo is managed-only if `eng/SourceBuild.props` contains +h `true`. If this is true, + this step is not necessary. Otherwise, specify `sourceBuildParameters` + in the `jobs.yml` template's parameters like this: ```yaml sourceBuildParameters: @@ -200,63 +244,92 @@ To opt in: #### End result -Submit the changes above in a PR and include [@source-build-internal](https://github.com/orgs/dotnet/teams/source-build-internal) as a reviewer. The jobs (or job, if managed-only) are automatically be added to CI in the existing pipeline alongside existing jobs, +Submit the changes above in a PR and include +[@source-build-internal](https://github.com/orgs/dotnet/teams/source-build-internal) +as a reviewer. The jobs (or job, if managed-only) are automatically be added +to CI in the existing pipeline alongside existing jobs, with a name like `Build Source-Build ()`: ![Build jobs image with source build leg](img/ci-job.png) -Once this PR works, run a mock official build (AKA "validation build") in your official build definition. The usual workflow is to push a `dev//arpow` branch to the AzDO repo and then queue a build on that branch. This makes sure that merging the PR won't immediately break the official build: -`enableSourceBuild: true` does add job(s) to the official build, not just PR validation. +Once this PR works, run a mock official build (AKA "validation build") in your +official build definition. The usual workflow is to push a +`dev//arpow` branch to the AzDO repo and then queue a build on that +branch. This makes sure that merging the PR won't immediately break the +official build: `enableSourceBuild: true` does add job(s) to the official +build, not just PR validation. -If the PR is green, but merging it produces red PR or Official builds, immediately let the source build team know about the failure and revert the +If the PR is green, but merging it produces red PR or Official builds, +immediately let the source build team know about the failure and revert the source build PR to unblock dev work. ### Advanced: granular templates -If the repo doesn't use the basic Arcade jobs template, or has advanced job templating infra built on top of the Arcade jobs template, the simple -`enableSourceBuild` flag might not work out. There are a few more granular templates to use in this case. +If the repo doesn't use the basic Arcade jobs template, or has advanced job +templating infra built on top of the Arcade jobs template, the simple +`enableSourceBuild` flag might not work out. There are a few more granular +templates to use in this case. -Look at the documentation in each YAML file itself to figure out how to use it properly, and if it fits the scenario. This list is only an overview. +Look at the documentation in each YAML file itself to figure out how to use +it properly, and if it fits the scenario. This list is only an overview. #### `eng/common/templates/jobs/source-build.yml` -This is one level deeper than `eng/common/templates/jobs/jobs.yml`. It is a `jobs` template that produces just the set of source-build jobs based on the -specified `platforms`. Or, just one job with the default platform, if managed-only. +This is one level deeper than `eng/common/templates/jobs/jobs.yml`. It is +a `jobs` template that produces just the set of source-build jobs based +on the specified `platforms`. Or, just one job with the default platform, +if managed-only. #### `eng/common/templates/job/source-build.yml` -This template defines a single `job` that runs source build on a specifiedplatform. +This template defines a single `job` that runs source build on a +specifiedplatform. #### `eng/common/templates/steps/source-build.yml` -This template defines the build `steps` for a single source build job. This is the most granular template, and may be useful if some repo-specific preamble or -cleanup steps are required, or if the repo already has job matrix templates and this just happens to fit in nicely. +This template defines the build `steps` for a single source build job. +This is the most granular template, and may be useful if some +repo-specific preamble or cleanup steps are required, or if the repo +already has job matrix templates and this just happens to fit in nicely. ### Official build publishing -Publishing [intermediate nupkg]s in the official build is handled by the standard Arcade publish infrastructure, which should already be set up in the -repo. The source build steps handle uploading the [intermediate nupkg] to the pipeline in the standard way that Arcade will detect and publish. +Publishing [intermediate nupkg]s in the official build is handled by the +standard Arcade publish infrastructure, which should already be set up +in the repo. The source build steps handle uploading the +[intermediate nupkg] to the pipeline in the standard way that Arcade +will detect and publish. [intermediate nupkg]: https://github.com/dotnet/source-build/blob/master/Documentation/planning/arcade-powered-source-build/intermediate-nupkg.md ## Add Downstream Dependency -The graph defined by `eng/Version.Details.xml` defines what is included in source build. This dependency graph starts at -[dotnet/installer](https://github.com/dotnet/installer/blob/main/eng/Version.Details.xml). The .NET source build insfrastructure walks this graph and determines -the full set of repos to build. Source build will only build one copy/commit of each repo (the first commit found in the dependency graph). Therefore, when adding -a new repositories, a dependency must be created within the `eng/Version.Details.xml` graph. To do this, go to the repo which depends on the new repo and add a [new -source build dependency](#engversiondetailsxml) to the new source build repo. +The graph defined by `eng/Version.Details.xml` defines what is included +in source build. This dependency graph starts at +[dotnet/installer](https://github.com/dotnet/installer/blob/main/eng/Version.Details.xml). +The .NET source build insfrastructure walks this graph and determines +the full set of repos to build. Source build will only build one copy/commit +of each repo (the first commit found in the dependency graph). Therefore, +when adding a new repositories, a dependency must be created within the +`eng/Version.Details.xml` graph. To do this, go to the repo which depends on +the new repo and add a +[new source build dependency](#engversiondetailsxml) to the new source build +repo. ## Validate -Once the downstream dependency(s) are added to the new repo and those changes flow into `dotnet/installer`, a complete .NET source tarball can be built. -This will validate that no prebuilts were added to the system and everything is functioning correctly. Please notify -[@source-build-internal](https://github.com/orgs/dotnet/teams/source-build-internal) to be on the lookout for the new repo and they will validate as necessary. - -# Additional resources - -- For more details about how the build executes, see -[Arcade's build tools](https://github.com/dotnet/arcade/tree/master/src/Microsoft.DotNet.Arcade.Sdk/tools/SourceBuild). -- The source code for the build tasks that run for prebuilt validation and intermediate nupkg dependency reading are maintained in -[Arcade](https://github.com/dotnet/arcade/tree/master/src/Microsoft.DotNet.SourceBuild) as well. \ No newline at end of file +Once the downstream dependency(s) are added to the new repo and those changes +flow into `dotnet/installer`, a complete .NET source tarball can be built. +This will validate that no prebuilts were added to the system and everything +is functioning correctly. Please notify +[@source-build-internal](https://github.com/orgs/dotnet/teams/source-build-internal) +to be on the lookout for the new repo and they will validate as necessary. + +## Additional resources + +* For more details about how the build executes, see + [Arcade's build tools](https://github.com/dotnet/arcade/tree/master/src/Microsoft.DotNet.Arcade.Sdk/tools/SourceBuild). +* The source code for the build tasks that run for prebuilt validation and + intermediate nupkg dependency reading are maintained in + [Arcade](https://github.com/dotnet/arcade/tree/master/src/Microsoft.DotNet.SourceBuild) + as well. diff --git a/Documentation/sourcebuild-in-repos/update-dependencies.md b/Documentation/sourcebuild-in-repos/update-dependencies.md index 57b1e61c0f..b349afb39a 100644 --- a/Documentation/sourcebuild-in-repos/update-dependencies.md +++ b/Documentation/sourcebuild-in-repos/update-dependencies.md @@ -1,28 +1,53 @@ # Updating a dependency -In most cases, dependency flow should automatically update the packages you depend on. There are some special considerations and things to keep in mind when doing manual updates. If you are manually updating a version, also see [the doc on new dependencies](new-dependencies.md) for special considerations. +In most cases, dependency flow should automatically update the packages you +depend on. There are some special considerations and things to keep in mind +when doing manual updates. If you are manually updating a version, also see +[the doc on new dependencies](new-dependencies.md) for special considerations. ## Internal packages -If you are manually updating a package, please make sure it's from a compatible branch (e.g. runtime release/6.0 to sdk release/6.0.1xx, release/6.0.2xx, etc). Package versions that you are updating to should be source-built in their respective repos. If the version you need is produced in a branch that is not yet source-build-compatible please let the [source-build team](https://github.com/orgs/dotnet/teams/source-build-internal) know. +If you are manually updating a package, please make sure it's from a +compatible branch (e.g. runtime release/6.0 to sdk release/6.0.1xx, +release/6.0.2xx, etc). Package versions that you are updating to should +be source-built in their respective repos. If the version you need is +produced in a branch that is not yet source-build-compatible please let the +[source-build team](https://github.com/orgs/dotnet/teams/source-build-internal) +know. -Another common error we see is updating eng/Versions.props but not eng/Version.Details.xml. This causes problems for source-build because we depend on these files being updated in lockstep. Please prefer updating with Darc - it takes care of these issues - or, if a manual update really is necessary, make sure you update both files. +Another common error we see is updating eng/Versions.props but not +eng/Version.Details.xml. This causes problems for source-build because we +depend on these files being updated in lockstep. Please prefer updating with +Darc - it takes care of these issues - or, if a manual update really is +necessary, make sure you update both files. Example Darc command: `darc update-dependencies --name MyCoolPackage -v 1.2.3` ## External packages -Updating a non-Microsoft (e.g. Newtonsoft.Json 9.0.1 to 13.0.1) or non-Arcade (e.g. ApplicationInsights) package is typically equivalent to adding the new version all over again. Please [log an issue](https://github.com/dotnet/source-build/issues/new/choose) to discuss this. You can check if the external package you want is already included in source-build in the [source-build-externals](https://github.com/dotnet/source-build-externals) repo. +Updating a non-Microsoft (e.g. Newtonsoft.Json 9.0.1 to 13.0.1) or +non-Arcade (e.g. ApplicationInsights) package is typically equivalent to +adding the new version all over again. Please +[log an issue](https://github.com/dotnet/source-build/issues/new/choose) +to discuss this. You can check if the external package you want is already +included in source-build in the +[source-build-externals](https://github.com/dotnet/source-build-externals) repo. ## Splitting, combining, and moving packages -These operations often end up causing source-build issues. A typical case of what can happen is -1. Package A is produced in version 1. -2. In version 2, Package A is split into Package A1 and Package A2. -3. A downstream repo is never updated to take the split packages. -4. The version 2 source-build succeeds because Package A exists in the [previously-source-built archive](build-info.md#Single-version_and_single-RID_build), but no new version of Package A is produced. -5. Source-build version 3 fails because Package A no longer exists in the previously-source-built archive either. - +These operations often end up causing source-build issues. A typical case of +what can happen is -So please keep in mind consumers of your packages and try to keep them informed of these kinds of changes. If you are the consuming repo, consider tracking PRs in the repos that produce your dependencies. \ No newline at end of file +1. Package A is produced in version 1. +1. In version 2, Package A is split into Package A1 and Package A2. +1. A downstream repo is never updated to take the split packages. +1. The version 2 source-build succeeds because Package A exists in the + [previously-source-built archive](build-info.md#Single-version_and_single-RID_build), + but no new version of Package A is produced. +1. Source-build version 3 fails because Package A no longer exists in + the previously-source-built archive either. + +So please keep in mind consumers of your packages and try to keep them +informed of these kinds of changes. If you are the consuming repo, consider +tracking PRs in the repos that produce your dependencies. \ No newline at end of file From 61d1ec40ba0b3afb3bb4bfcb143e9ab4e3f27210 Mon Sep 17 00:00:00 2001 From: Chris Rummel Date: Wed, 4 May 2022 11:50:08 -0500 Subject: [PATCH 16/16] Address review comments. --- .../sourcebuild-in-repos/new-dependencies.md | 40 +++++++------------ 1 file changed, 15 insertions(+), 25 deletions(-) diff --git a/Documentation/sourcebuild-in-repos/new-dependencies.md b/Documentation/sourcebuild-in-repos/new-dependencies.md index e72d4ccebc..dde92c9a63 100644 --- a/Documentation/sourcebuild-in-repos/new-dependencies.md +++ b/Documentation/sourcebuild-in-repos/new-dependencies.md @@ -42,19 +42,16 @@ see [installer's F# dependency](https://github.com/dotnet/installer/blob/ba1739a You can find the version needed by running `darc get-build` or using [BAR](https://aka.ms/bar). -## Microsoft dependencies - -.NET dependencies are from a Microsoft .NET project, like -[dotnet/roslyn](https://github.com/dotnet/roslyn), -[dotnet/runtime](https://github.com/dotnet/runtime), -and [dotnet/fsharp](https://github.com/dotnet/fsharp). These repos use -Arcade to build and publish. Adding a new .NET dependency is usually -quite easy. Internal dependencies are from Microsoft repos but not .NET, -like [Microsoft/msbuild](https://github.com/dotnet/msbuild), -[NuGet/NuGet.Client](https://github.com/NuGet/NuGet.Client), -and [Microsoft/ApplicationInsights](https://github.com/Microsoft/ApplicationInsights-dotnet). -Adding a new internal dependency is usually pretty straightforward but does -have some edge cases. Use this checklist: +## Adding dependencies + +Source build classifies dependencies in the following ways + +1. .NET - a dependency on a component from the .NET org - e.g. dotnet/runtime +1. Microsoft - a dependency on a component from the Microsoft org - e.g. microsoft/vstest +1. External - a dependency on a component outside of Microsoft/.NET - e.g. JamesNK/Newtonsoft.Json + +The following checklist can be used to determine how to handle each type of +dependency and the nuances it may have. 1. Are you already using a package from the same repo and is the new dependency already source-built? You can determine this by checking if @@ -72,7 +69,7 @@ have some edge cases. Use this checklist: 1. There's probably an issue with source-building this package. Please talk to a [source-build team member](https://github.com/orgs/dotnet/teams/source-build-internal) about why that is and whether we can fix it. -1. Is this a Microsoft repo that uses Arcade to build? +1. Is this a repo that uses Arcade to build? 1. Does the foreign repo depend on your repo, directly or indirectly? i.e. would adding the dependency create a cycle? 1. This isn't necessarily a deal-breaker - it can sometimes be worked @@ -84,22 +81,15 @@ have some edge cases. Use this checklist: in an appropriate channel. 1. If neither of these caveats apply you should be in good shape. Follow the instructions under "Basics" above. -1. Source-build has in the past used Arcade shims to allow non-Arcade repos - to build appropriate packages for source-build. Please contact the - [source-build team](https://github.com/orgs/dotnet/teams/source-build-internal) - to determine if this is a workable approach for your foreign repo. - -## External dependencies - -External (non-Microsoft or even non-dotnet) dependencies need to be carefully -considered for source-build in addition to the licensing issues you are -probably already familiar with. - 1. Dependencies that have no code (e.g. SDKs with just props and targets) can usually be added using the [source-build text-only-package process](https://github.com/dotnet/source-build-reference-packages/tree/main/src/textOnlyPackages/src). If the package is not already included there, you can [open a PR](https://github.com/dotnet/source-build-reference-packages/pulls) or [file an issue](https://github.com/dotnet/source-build/issues/new/choose) to include it. +1. Source-build has in the past used Arcade shims to allow non-Arcade repos + to build appropriate packages for source-build. Please + [log an issue](https://github.com/dotnet/source-build/issues/new/choose) + to determine if this is a workable approach for your foreign repo. 1. We build some external dependencies in the [dotnet/source-build-externals](https://github.com/dotnet/source-build-externals) repo. Good targets for this generally have very few if any dependencies and very simple build processes.