Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Documentation/feature-band-source-building.md
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ These are shared runtime and foundational components from the 1xx band:
- Include shared runtime and foundational components that all feature bands
depend on

For the package-version precedence between PSB, current source-built, and shared
component inputs, see [package dependency flow](package-dependency-flow.md).

### Select the Branch-Pinned Input Versions

Throughout the rest of this document, "current" and "previous" describe the
Expand Down
122 changes: 73 additions & 49 deletions Documentation/package-dependency-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,20 @@ considered a [poison leak](./leak-detection.md) and is not permitted during a
source build as it breaks the notion of building the product entirely from
source. This hinders the ability to service the product.

### Shared Component Packages

Non-1xx feature-band builds consume shared runtime and foundational packages
from the corresponding 1xx build. Unlike previously source-built (PSB)
packages, these packages can intentionally contribute to the final product.
See [feature-band source building](./feature-band-source-building.md) for the
artifact relationship between bands.

## Package Versions

Package dependencies defined using [Arcade's dependency
patterns](https://github.com/dotnet/arcade/blob/main/Documentation/Darc.md) will
get lifted dynamically during a source build if the following conditions are
met:
Under the dependency-only flow, package dependencies defined using
[Arcade's dependency
patterns](https://github.com/dotnet/arcade/blob/main/Documentation/Darc.md) are
eligible for lifting during a source build when these conditions are met:

1. The dependency is declared in the Version.Details.xml file.

Expand Down Expand Up @@ -78,51 +86,67 @@ met:
graph](https://github.com/dotnet/dotnet/tree/main/repo-projects). This
reference does not have to be direct, it can be transitive.

**{VMR repo project}.proj**

```xml
...
<RepositoryReference Include="command-line-api" />
...
```

When these conditions are met during a source build, the infrastructure will
scan the Version.Details.xml file and dynamically create two new Versions.props
files containing updated version properties for all non-pinned dependencies.

**PackageVersions.Previous.props:** This will contain version properties with
the package versions from the [previous release of source
build](#previous-source-built-packages). If a new package exists that has never
been released before, it will not have a version property defined.

```xml
...
<SystemCommandLineVersion>2.0.0-beta3</SystemCommandLineVersion>
...
```

**PackageVersions.Current.props:** This will contain version properties with the
package versions from the [current source
build](#current-source-built-packages). If a package comes from a repo that has
not been built yet, it will not have a version property defined.

```xml
...
<SystemCommandLineVersion>2.0.0-beta4</SystemCommandLineVersion>
...
```

These two version.props files get imported by the arcade source build
infrastructure after the repo's Version.props file. Therefore the repo's
Versions.props property versions get overridden by the source build versions. In
the case of the `SystemCommandLineVersion` example, the current source build
version, 2.0.0-beta4, would win. All msbuild references (e.g. project
PackageReferences) to these Versions.props properties pick up the newer
versions. This is known as package version lifting since it lifts the originally
defined package version to the current source built version. This behavior only
applies to source build in the context of the
[VMR](https://github.com/dotnet/dotnet) (see also [Repo Level Source
Builds](#repo-level-source-builds)).
For each repository build, the VMR writes these repository-specific files:

- `PackageVersions.<repo>.Previous.props` describes PSB packages.
- `PackageVersions.<repo>.Current.props` describes packages produced by
dependencies earlier in the current build.
- `PackageVersions.<repo>.SharedComponents.props` describes shared-component
inputs when they apply.
- `PackageVersions.<repo>.Snapshot.props` is an unfiltered snapshot of current
packages used to attribute package production. It is not an imported version
override.
- `PackageVersions.<repo>.props` aggregates the applicable input files.

`WritePackageVersionsProps` generates the property names from package IDs and a
caller-provided set of suffixes. Depending on the configured flow type, it
writes every available package or only dependencies declared by the repository.
The aggregate props file is imported after the repository's checked-in
`Versions.props` and imports the generated inputs in this order:

1. `Previous`
2. `Current`
3. `SharedComponents`

MSBuild properties use last-assignment-wins semantics. For values that reach
repository evaluation, a property in a later input replaces the same property
from an earlier input. This is package version lifting: package references that
use these properties request versions available from the effective VMR inputs
instead of the repository defaults. This behavior applies only to source build
in the [VMR](https://github.com/dotnet/dotnet) (see also
[Repo Level Source Builds](#repo-level-source-builds)).

### Property suffixes do not guarantee provenance

The PSB generator writes the usual `*Version` and `*PackageVersion` properties
and also writes `*PreviousVersion` properties. Shared-component generation uses
the same suffix set, while current generation uses only the usual suffixes.
Consequently, `PreviousVersion` describes the suffix used while generating a
property; it does not guarantee that the property's final value came from PSB.

If PSB and shared-component inputs contain the same package ID, both can
generate the same properties. Because `SharedComponents` is imported after
`Previous`, the shared-component assignments win. The effective property set is
therefore determined by the complete PSB, current, and shared-component input
matrix. A dependency update or change to current/shared-component inputs can
expose a bootstrap mismatch even when the PSB archive is unchanged and an
earlier build passed.

The VMR separately rejects package ID conflicts between shared components and
current packages whose repository origin is not `source-build-assets`. That
check does not prevent a PSB/shared-component property collision.

### Preserve versions that require a specific origin

Generated package-version properties select an effective version; they are not
provenance guarantees. If a component requires a version from a specific
origin, preserve it in a distinct, component-specific property before later
imports can overwrite the generic property, and use that property for the
dependency.

Standalone repository builds do not receive the VMR-generated files. The
component-specific property therefore also needs an appropriate fallback to the
repository's checked-in or current dependency property.

### Transitive Version Properties

Expand Down
18 changes: 9 additions & 9 deletions Documentation/understanding-source-build.md
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,8 @@ Together, these files form a consumer-specific set of version overrides. The
VMR uses the consumer's declared dependency metadata to choose which current,
previous, or shared-component versions replace repository defaults. It does not
treat every package available in a feed as an override.
The [package dependency flow guide](package-dependency-flow.md) is authoritative
for the generated property suffixes and aggregate import precedence.

**Example: lifting MSBuild's Roslyn compiler dependency.** MSBuild's
[Darc-generated dependency properties][msbuild-version-details] initially set
Expand All @@ -569,15 +571,13 @@ MSBuild uses `MicrosoftNetCompilersToolsetVersion` for its
<MicrosoftNetCompilersToolsetPackageVersion>4.14.0</MicrosoftNetCompilersToolsetPackageVersion>
```

`PackageVersions.msbuild.props` imports the previous file first and the current
file second. The combined overrides are applied after MSBuild's repository
defaults, so `4.14.0` wins. MSBuild therefore consumes the compiler toolset
produced by the current Roslyn build rather than its Darc-pinned version or the
previously source-built version.

See [package dependency flow](package-dependency-flow.md) for a worked
description of current and previous package-version props and the metadata that
enables lifting.
For this 1xx example there is no shared-component input, so the aggregate imports
the previous file first and the current file second. The combined overrides are
applied after MSBuild's repository defaults, so `4.14.0` wins. MSBuild therefore
consumes the compiler toolset produced by the current Roslyn build rather than
its Darc-pinned version or the previously source-built version. For the general
precedence contract, including non-1xx shared-component inputs, see
[package dependency flow](package-dependency-flow.md).

This yields an important debugging rule:

Expand Down