diff --git a/.azure/pipelines/ci.yml b/.azure/pipelines/ci.yml index caa6557d49..67d59a247f 100644 --- a/.azure/pipelines/ci.yml +++ b/.azure/pipelines/ci.yml @@ -29,7 +29,9 @@ variables: - ${{ if or(eq(variables['System.TeamProject'], 'public'), in(variables['Build.Reason'], 'PullRequest')) }}: - name: _BuildArgs value: '' + jobs: +# Code check - template: jobs/default-build.yml parameters: jobName: Code_check @@ -38,6 +40,10 @@ jobs: steps: - powershell: ./eng/scripts/CodeCheck.ps1 -ci displayName: Run eng/scripts/CodeCheck.ps1 + artifacts: + - name: Code_Check_Logs + path: artifacts/log/ + publishOnError: true # Build Windows (x64/x86) - template: jobs/default-build.yml @@ -171,6 +177,7 @@ jobs: -bl:artifacts/log/build.macos.binlog $(_BuildArgs) installNodeJs: false + installJdk: false artifacts: - name: MacOS_x64_Packages path: artifacts/packages/ @@ -191,7 +198,6 @@ jobs: jobName: Linux_x64_build jobDisplayName: "Build: Linux x64" agentOs: Linux - installNodeJs: false steps: - script: ./build.sh --ci @@ -211,6 +217,7 @@ jobs: --arch x64 \ --build-installers \ --no-build-deps \ + --no-build-nodejs \ -p:OnlyPackPlatformSpecificPackages=true \ -p:BuildRuntimeArchive=false \ -p:LinuxInstallerType=deb \ @@ -224,12 +231,15 @@ jobs: --arch x64 \ --build-installers \ --no-build-deps \ + --no-build-nodejs \ -p:OnlyPackPlatformSpecificPackages=true \ -p:BuildRuntimeArchive=false \ -p:LinuxInstallerType=rpm \ -bl:artifacts/log/build.rpm.binlog \ $(_BuildArgs) displayName: Build RPM installers + installNodeJs: false + installJdk: false artifacts: - name: Linux_x64_Packages path: artifacts/packages/ @@ -260,6 +270,7 @@ jobs: -bl:artifacts/log/build.linux-arm.binlog $(_BuildArgs) installNodeJs: false + installJdk: false artifacts: - name: Linux_arm_Packages path: artifacts/packages/ @@ -290,6 +301,7 @@ jobs: -bl:artifacts/log/build.arm64.binlog $(_BuildArgs) installNodeJs: false + installJdk: false artifacts: - name: Linux_arm64_Packages path: artifacts/packages/ @@ -323,6 +335,7 @@ jobs: -bl:artifacts/log/build.musl.binlog $(_BuildArgs) installNodeJs: false + installJdk: false artifacts: - name: Linux_musl_x64_Packages path: artifacts/packages/ @@ -337,7 +350,7 @@ jobs: parameters: inputName: Linux_musl_x64 -# Build Linux Musl arm64 +# Build Linux Musl ARM64 - template: jobs/default-build.yml parameters: jobName: Linux_musl_arm64_build @@ -356,6 +369,7 @@ jobs: -bl:artifacts/log/build.musl.binlog $(_BuildArgs) installNodeJs: false + installJdk: false artifacts: - name: Linux_musl_arm64_Packages path: artifacts/packages/ @@ -499,7 +513,7 @@ jobs: version: 3.0.x installationPath: $(DotNetCoreSdkDir) includePreviewVersions: true - - script: ./eng/scripts/ci-source-build.sh --ci --configuration Release /p:BuildManaged=true + - script: ./eng/scripts/ci-source-build.sh --ci --configuration Release /p:BuildManaged=true /p:BuildNodeJs=false displayName: Run ci-source-build.sh - task: PublishBuildArtifacts@1 displayName: Upload logs diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 86a87beb59..3acc059820 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -14,7 +14,7 @@ /src/Hosting/ @tratcher @anurse /src/Http/ @tratcher @jkotalik @anurse /src/Middleware/ @tratcher @anurse -/src/ProjectTemplates/ @ryanbrandenburg +# /src/ProjectTemplates/ @ryanbrandenburg /src/Security/ @tratcher @anurse /src/Servers/ @tratcher @jkotalik @anurse @halter73 /src/Middleware/Rewrite @jkotalik @anurse diff --git a/NuGet.config b/NuGet.config index eda7e2c3e9..d0a37a8d8e 100644 --- a/NuGet.config +++ b/NuGet.config @@ -3,11 +3,15 @@ - + + + + + diff --git a/build.ps1 b/build.ps1 index 018c3970b7..17020044ed 100644 --- a/build.ps1 +++ b/build.ps1 @@ -183,7 +183,7 @@ elseif ($Projects) { } # When adding new sub-group build flags, add them to this check. elseif((-not $BuildNative) -and (-not $BuildManaged) -and (-not $BuildNodeJS) -and (-not $BuildInstallers) -and (-not $BuildJava)) { - Write-Warning "No default group of projects was specified, so building the 'managed' subsets of projects. Run ``build.cmd -help`` for more details." + Write-Warning "No default group of projects was specified, so building the 'managed' and its dependent subsets of projects. Run ``build.cmd -help`` for more details." # This goal of this is to pick a sensible default for `build.cmd` with zero arguments. # Now that we support subfolder invokations of build.cmd, we will be pushing to have build.cmd build everything (-all) by default @@ -191,6 +191,25 @@ elseif((-not $BuildNative) -and (-not $BuildManaged) -and (-not $BuildNodeJS) -a $BuildManaged = $true } +if ($BuildManaged -or ($All -and (-not $NoBuildManaged))) { + if ((-not $BuildNodeJS) -and (-not $NoBuildNodeJS)) { + $node = Get-Command node -ErrorAction Ignore -CommandType Application + + if ($node) { + $nodeHome = Split-Path -Parent (Split-Path -Parent $node.Path) + Write-Host -f Magenta "Building of C# project is enabled and has dependencies on NodeJS projects. Building of NodeJS projects is enabled since node is detected in $nodeHome." + } + else { + Write-Host -f Magenta "Building of NodeJS projects is disabled since node is not detected on Path and no BuildNodeJs or NoBuildNodeJs setting is set explicitly." + $NoBuildNodeJS = $true + } + } + + if ($NoBuildNodeJS){ + Write-Warning "Some managed projects depend on NodeJS projects. Building NodeJS is disabled so the managed projects will fallback to using the output from previous builds. The output may not be correct or up to date." + } +} + if ($BuildInstallers) { $MSBuildArguments += "/p:BuildInstallers=true" } if ($BuildManaged) { $MSBuildArguments += "/p:BuildManaged=true" } if ($BuildNative) { $MSBuildArguments += "/p:BuildNative=true" } diff --git a/build.sh b/build.sh index c170ac1844..ad4ce2c1c8 100755 --- a/build.sh +++ b/build.sh @@ -213,7 +213,7 @@ elif [ ! -z "$build_projects" ]; then elif [ -z "$build_managed" ] && [ -z "$build_nodejs" ] && [ -z "$build_java" ] && [ -z "$build_native" ] && [ -z "$build_installers" ]; then # This goal of this is to pick a sensible default for `build.sh` with zero arguments. # We believe the most common thing our contributors will work on is C#, so if no other build group was picked, build the C# projects. - __warn "No default group of projects was specified, so building the 'managed' subset of projects. Run ``build.sh --help`` for more details." + __warn "No default group of projects was specified, so building the 'managed' and its dependent subset of projects. Run ``build.sh --help`` for more details." build_managed=true fi @@ -221,6 +221,21 @@ if [ "$build_deps" = false ]; then msbuild_args[${#msbuild_args[*]}]="-p:BuildProjectReferences=false" fi +if [ "$build_managed" = true ] || (["$build_all" = true ] && [ "$build_managed" != false ]); then + if [ -z "$build_nodejs" ]; then + if [ -x "$(command -v node)" ]; then + __warn "Building of C# project is enabled and has dependencies on NodeJS projects. Building of NodeJS projects is enabled since node is detected on PATH." + else + __warn "Building of NodeJS projects is disabled since node is not detected on Path and no BuildNodeJs or NoBuildNodeJs setting is set explicitly." + build_nodejs=false + fi + fi + + if [ "$build_nodejs" = false ]; then + __warn "Some managed projects depend on NodeJS projects. Building NodeJS is disabled so the managed projects will fallback to using the output from previous builds. The output may not be correct or up to date." + fi +fi + # Only set these MSBuild properties if they were explicitly set by build parameters. [ ! -z "$build_java" ] && msbuild_args[${#msbuild_args[*]}]="-p:BuildJava=$build_java" [ ! -z "$build_native" ] && msbuild_args[${#msbuild_args[*]}]="-p:BuildNative=$build_native" diff --git a/docs/BuildFromSource.md b/docs/BuildFromSource.md index 53938c189b..7740ec6140 100644 --- a/docs/BuildFromSource.md +++ b/docs/BuildFromSource.md @@ -97,14 +97,14 @@ The cause of this problem is that the solution you are using does not include th ``` ### Common error: Unable to locate the .NET Core SDK - + Executing `.\restore.cmd` or `.\build.cmd` may produce these errors: > error : Unable to locate the .NET Core SDK. Check that it is installed and that the version specified in global.json (if any) matches the installed version. > error MSB4236: The SDK 'Microsoft.NET.Sdk' specified could not be found. In most cases, this is because the option _Use previews of the .NET Core SDK_ in VS2019 is not checked. Start Visual Studio, go to _Tools > Options_ and check _Use previews of the .NET Core SDK_ under _Environment > Preview Features_. - + ## Building with Visual Studio Code Using Visual Studio Code with this repo requires setting environment variables on command line first. @@ -138,6 +138,8 @@ On macOS/Linux: ./build.sh ``` +By default, all of the C# projects are built. Some C# projects requires NodeJS to be installed to compile JavaScript assets which are then checked in as source. If NodeJS is detected on the path, the NodeJS projects will be compiled as part of building C# projects. If NodeJS is not detected on the path, the JavaScript assets checked in previously will be used instead. To disable building NodeJS projects, specify /p:BuildNodeJs=false on the command line. + ### Using `dotnet` on command line in this repo Because we are using pre-release versions of .NET Core, you have to set a handful of environment variables diff --git a/eng/Build.props b/eng/Build.props index eba7a2ac91..ef1a7776b6 100644 --- a/eng/Build.props +++ b/eng/Build.props @@ -4,14 +4,16 @@ - true - true - true - true + true + true + true + true + + - @@ -102,6 +104,7 @@ + Microsoft.AspNetCore.Hosting; diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index 1e7f2fa1cf..2c8002b211 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -9,289 +9,289 @@ --> - + https://github.com/aspnet/Blazor - dd092c2236cf9375b50e19295dd2faf36e6221f6 + b2c48dd8c9099f71908fac26089cbea2c76d06a1 - + https://github.com/aspnet/AspNetCore-Tooling - 65994cb6ffd2d8da87db74e2b3e34cb5e350aff0 + 448a88e86d20fd9315901f663318d64c9c6841bf - + https://github.com/aspnet/AspNetCore-Tooling - 65994cb6ffd2d8da87db74e2b3e34cb5e350aff0 + 448a88e86d20fd9315901f663318d64c9c6841bf - + https://github.com/aspnet/AspNetCore-Tooling - 65994cb6ffd2d8da87db74e2b3e34cb5e350aff0 + 448a88e86d20fd9315901f663318d64c9c6841bf - + https://github.com/aspnet/AspNetCore-Tooling - 65994cb6ffd2d8da87db74e2b3e34cb5e350aff0 + 448a88e86d20fd9315901f663318d64c9c6841bf - + https://github.com/aspnet/EntityFrameworkCore - 49f9f7632c742108e5652f182922cc35c19c9162 + 07ed34e80585ca9575ea0265921d42a203193b21 - + https://github.com/aspnet/EntityFrameworkCore - 49f9f7632c742108e5652f182922cc35c19c9162 + 07ed34e80585ca9575ea0265921d42a203193b21 - + https://github.com/aspnet/EntityFrameworkCore - 49f9f7632c742108e5652f182922cc35c19c9162 + 07ed34e80585ca9575ea0265921d42a203193b21 - + https://github.com/aspnet/EntityFrameworkCore - 49f9f7632c742108e5652f182922cc35c19c9162 + 07ed34e80585ca9575ea0265921d42a203193b21 - + https://github.com/aspnet/EntityFrameworkCore - 49f9f7632c742108e5652f182922cc35c19c9162 + 07ed34e80585ca9575ea0265921d42a203193b21 - + https://github.com/aspnet/EntityFrameworkCore - 49f9f7632c742108e5652f182922cc35c19c9162 + 07ed34e80585ca9575ea0265921d42a203193b21 - + https://github.com/aspnet/EntityFrameworkCore - 49f9f7632c742108e5652f182922cc35c19c9162 + 07ed34e80585ca9575ea0265921d42a203193b21 - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe https://github.com/dotnet/corefx @@ -412,25 +412,25 @@ https://github.com/dotnet/corefx 80f411d58df8338ccd9430900b541a037a9cb383 - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe - + https://github.com/dotnet/arcade - a190d4865fe3c86a168ec49c4fc61c90c96ae051 + b1c2f33f0cef32d1df6e7f388017fd6761d3fcad - + https://github.com/dotnet/arcade - a190d4865fe3c86a168ec49c4fc61c90c96ae051 + b1c2f33f0cef32d1df6e7f388017fd6761d3fcad - + https://github.com/dotnet/arcade - a190d4865fe3c86a168ec49c4fc61c90c96ae051 + b1c2f33f0cef32d1df6e7f388017fd6761d3fcad - + https://github.com/aspnet/Extensions - 54d000fda95c2c1f05b13a2e910fc91994da8eb8 + 86469ee35cf718e0122f16f52b486303dcfbb1fe https://github.com/dotnet/roslyn diff --git a/eng/Versions.props b/eng/Versions.props index 4f48ab6d95..d1befbd14a 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -55,7 +55,7 @@ --> - 1.0.0-beta.19369.2 + 1.0.0-beta.19404.1 3.3.0-beta3-19401-01 @@ -90,82 +90,82 @@ 3.0.0-preview8.19378.8 - 5.0.0-alpha1.19403.2 + 5.0.0-alpha1.19405.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 - 3.0.0-preview9.19401.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 + 3.0.0-preview9.19405.2 - 3.0.0-preview9.19402.9 - 3.0.0-preview9.19402.9 - 3.0.0-preview9.19402.9 - 3.0.0-preview9.19402.9 - 3.0.0-preview9.19402.9 - 3.0.0-preview9.19402.9 - 3.0.0-preview9.19402.9 + 3.0.0-preview9.19405.13 + 3.0.0-preview9.19405.13 + 3.0.0-preview9.19405.13 + 3.0.0-preview9.19405.13 + 3.0.0-preview9.19405.13 + 3.0.0-preview9.19405.13 + 3.0.0-preview9.19405.13 - 5.0.0-alpha1.19381.2 - 5.0.0-alpha1.19381.2 - 5.0.0-alpha1.19381.2 - 5.0.0-alpha1.19381.2 + 5.0.0-alpha1.19407.1 + 5.0.0-alpha1.19407.1 + 5.0.0-alpha1.19407.1 + 5.0.0-alpha1.19407.1 - - $(RestoreSources); - https://dotnetfeed.blob.core.windows.net/dotnet-core/index.json; - https://dotnetfeed.blob.core.windows.net/aspnet-blazor/index.json; - https://dotnetfeed.blob.core.windows.net/aspnet-extensions/index.json; - https://dotnetfeed.blob.core.windows.net/aspnet-entityframeworkcore/index.json; - https://dotnetfeed.blob.core.windows.net/aspnet-aspnetcore-tooling/index.json; - https://grpc.jfrog.io/grpc/api/nuget/v3/grpc-nuget-dev; - - - $(RestoreSources); - https://dotnet.myget.org/F/roslyn/api/v3/index.json; - - - - $(RestoreSources); - https://dotnet.myget.org/F/aspnetcore-dev/api/v3/index.json; - - + https://dotnetcli.blob.core.windows.net/dotnet/ diff --git a/eng/Workarounds.props b/eng/Workarounds.props index 0fa6edaeab..a56cf44b46 100644 --- a/eng/Workarounds.props +++ b/eng/Workarounds.props @@ -8,25 +8,6 @@ portable - - - $(RepoRoot)NuGet.config - - - - - - $(RestoreSources); - https://dotnet.myget.org/F/roslyn-tools/api/v3/index.json; - - - false diff --git a/eng/Workarounds.targets b/eng/Workarounds.targets index ed0324f744..f5c74cdd43 100644 --- a/eng/Workarounds.targets +++ b/eng/Workarounds.targets @@ -29,12 +29,6 @@ - - - $(RestoreSources); - https://dotnet.myget.org/F/aspnetcore-tools/api/v3/index.json; - - diff --git a/eng/common/init-tools-native.ps1 b/eng/common/init-tools-native.ps1 index 9d18645f45..8cf18bcfeb 100644 --- a/eng/common/init-tools-native.ps1 +++ b/eng/common/init-tools-native.ps1 @@ -98,12 +98,18 @@ try { } Write-Verbose "Installing $ToolName version $ToolVersion" - Write-Verbose "Executing '$InstallerPath $LocalInstallerArguments'" + Write-Verbose "Executing '$InstallerPath $($LocalInstallerArguments.Keys.ForEach({"-$_ '$($LocalInstallerArguments.$_)'"}) -join ' ')'" & $InstallerPath @LocalInstallerArguments if ($LASTEXITCODE -Ne "0") { $errMsg = "$ToolName installation failed" if ((Get-Variable 'DoNotAbortNativeToolsInstallationOnFailure' -ErrorAction 'SilentlyContinue') -and $DoNotAbortNativeToolsInstallationOnFailure) { - Write-Warning $errMsg + $showNativeToolsWarning = $true + if ((Get-Variable 'DoNotDisplayNativeToolsInstallationWarnings' -ErrorAction 'SilentlyContinue') -and $DoNotDisplayNativeToolsInstallationWarnings) { + $showNativeToolsWarning = $false + } + if ($showNativeToolsWarning) { + Write-Warning $errMsg + } $toolInstallationFailure = $true } else { Write-Error $errMsg diff --git a/eng/common/init-tools-native.sh b/eng/common/init-tools-native.sh index 5f2e77f448..4dafaaca13 100755 --- a/eng/common/init-tools-native.sh +++ b/eng/common/init-tools-native.sh @@ -70,8 +70,7 @@ function ReadGlobalJsonNativeTools { # Only extract the contents of the object. local native_tools_list=$(echo $native_tools_section | awk -F"[{}]" '{print $2}') native_tools_list=${native_tools_list//[\" ]/} - native_tools_list=${native_tools_list//,/$'\n'} - native_tools_list="$(echo -e "${native_tools_list}" | tr -d '[[:space:]]')" + native_tools_list=$( echo "$native_tools_list" | sed 's/\s//g' | sed 's/,/\n/g' ) local old_IFS=$IFS while read -r line; do @@ -108,6 +107,7 @@ else installer_command+=" --baseuri $base_uri" installer_command+=" --installpath $install_bin" installer_command+=" --version $tool_version" + echo $installer_command if [[ $force = true ]]; then installer_command+=" --force" diff --git a/eng/common/internal-feed-operations.sh b/eng/common/internal-feed-operations.sh old mode 100644 new mode 100755 diff --git a/eng/common/native/CommonLibrary.psm1 b/eng/common/native/CommonLibrary.psm1 index 7a34c7e8a4..2a08d5246e 100644 --- a/eng/common/native/CommonLibrary.psm1 +++ b/eng/common/native/CommonLibrary.psm1 @@ -59,9 +59,38 @@ function DownloadAndExtract { -Verbose:$Verbose if ($UnzipStatus -Eq $False) { - Write-Error "Unzip failed" - return $False + # Retry Download one more time with Force=true + $DownloadRetryStatus = CommonLibrary\Get-File -Uri $Uri ` + -Path $TempToolPath ` + -DownloadRetries 1 ` + -RetryWaitTimeInSeconds $RetryWaitTimeInSeconds ` + -Force:$True ` + -Verbose:$Verbose + + if ($DownloadRetryStatus -Eq $False) { + Write-Error "Last attempt of download failed as well" + return $False + } + + # Retry unzip again one more time with Force=true + $UnzipRetryStatus = CommonLibrary\Expand-Zip -ZipPath $TempToolPath ` + -OutputDirectory $InstallDirectory ` + -Force:$True ` + -Verbose:$Verbose + if ($UnzipRetryStatus -Eq $False) + { + Write-Error "Last attempt of unzip failed as well" + # Clean up partial zips and extracts + if (Test-Path $TempToolPath) { + Remove-Item $TempToolPath -Force + } + if (Test-Path $InstallDirectory) { + Remove-Item $InstallDirectory -Force -Recurse + } + return $False + } } + return $True } diff --git a/eng/common/native/install-cmake-test.sh b/eng/common/native/install-cmake-test.sh new file mode 100755 index 0000000000..53ddf4e686 --- /dev/null +++ b/eng/common/native/install-cmake-test.sh @@ -0,0 +1,117 @@ +#!/usr/bin/env bash + +source="${BASH_SOURCE[0]}" +scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" + +. $scriptroot/common-library.sh + +base_uri= +install_path= +version= +clean=false +force=false +download_retries=5 +retry_wait_time_seconds=30 + +while (($# > 0)); do + lowerI="$(echo $1 | awk '{print tolower($0)}')" + case $lowerI in + --baseuri) + base_uri=$2 + shift 2 + ;; + --installpath) + install_path=$2 + shift 2 + ;; + --version) + version=$2 + shift 2 + ;; + --clean) + clean=true + shift 1 + ;; + --force) + force=true + shift 1 + ;; + --downloadretries) + download_retries=$2 + shift 2 + ;; + --retrywaittimeseconds) + retry_wait_time_seconds=$2 + shift 2 + ;; + --help) + echo "Common settings:" + echo " --baseuri Base file directory or Url wrom which to acquire tool archives" + echo " --installpath Base directory to install native tool to" + echo " --clean Don't install the tool, just clean up the current install of the tool" + echo " --force Force install of tools even if they previously exist" + echo " --help Print help and exit" + echo "" + echo "Advanced settings:" + echo " --downloadretries Total number of retry attempts" + echo " --retrywaittimeseconds Wait time between retry attempts in seconds" + echo "" + exit 0 + ;; + esac +done + +tool_name="cmake-test" +tool_os=$(GetCurrentOS) +tool_folder=$(echo $tool_os | awk '{print tolower($0)}') +tool_arch="x86_64" +tool_name_moniker="$tool_name-$version-$tool_os-$tool_arch" +tool_install_directory="$install_path/$tool_name/$version" +tool_file_path="$tool_install_directory/$tool_name_moniker/bin/$tool_name" +shim_path="$install_path/$tool_name.sh" +uri="${base_uri}/$tool_folder/$tool_name/$tool_name_moniker.tar.gz" + +# Clean up tool and installers +if [[ $clean = true ]]; then + echo "Cleaning $tool_install_directory" + if [[ -d $tool_install_directory ]]; then + rm -rf $tool_install_directory + fi + + echo "Cleaning $shim_path" + if [[ -f $shim_path ]]; then + rm -rf $shim_path + fi + + tool_temp_path=$(GetTempPathFileName $uri) + echo "Cleaning $tool_temp_path" + if [[ -f $tool_temp_path ]]; then + rm -rf $tool_temp_path + fi + + exit 0 +fi + +# Install tool +if [[ -f $tool_file_path ]] && [[ $force = false ]]; then + echo "$tool_name ($version) already exists, skipping install" + exit 0 +fi + +DownloadAndExtract $uri $tool_install_directory $force $download_retries $retry_wait_time_seconds + +if [[ $? != 0 ]]; then + echo "Installation failed" >&2 + exit 1 +fi + +# Generate Shim +# Always rewrite shims so that we are referencing the expected version +NewScriptShim $shim_path $tool_file_path true + +if [[ $? != 0 ]]; then + echo "Shim generation failed" >&2 + exit 1 +fi + +exit 0 \ No newline at end of file diff --git a/eng/common/native/install-cmake.sh b/eng/common/native/install-cmake.sh index 293af6017d..5f1a182fa9 100755 --- a/eng/common/native/install-cmake.sh +++ b/eng/common/native/install-cmake.sh @@ -69,7 +69,7 @@ tool_name_moniker="$tool_name-$version-$tool_os-$tool_arch" tool_install_directory="$install_path/$tool_name/$version" tool_file_path="$tool_install_directory/$tool_name_moniker/bin/$tool_name" shim_path="$install_path/$tool_name.sh" -uri="${base_uri}/$tool_folder/cmake/$tool_name_moniker.tar.gz" +uri="${base_uri}/$tool_folder/$tool_name/$tool_name_moniker.tar.gz" # Clean up tool and installers if [[ $clean = true ]]; then diff --git a/eng/common/performance/performance-setup.sh b/eng/common/performance/performance-setup.sh old mode 100644 new mode 100755 diff --git a/eng/common/pipeline-logging-functions.sh b/eng/common/pipeline-logging-functions.sh old mode 100644 new mode 100755 diff --git a/eng/common/post-build/darc-gather-drop.ps1 b/eng/common/post-build/darc-gather-drop.ps1 new file mode 100644 index 0000000000..93a0bd8328 --- /dev/null +++ b/eng/common/post-build/darc-gather-drop.ps1 @@ -0,0 +1,35 @@ +param( + [Parameter(Mandatory=$true)][int] $BarBuildId, # ID of the build which assets should be downloaded + [Parameter(Mandatory=$true)][string] $DropLocation, # Where the assets should be downloaded to + [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, # Token used to access Maestro API + [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = "https://maestro-prod.westus2.cloudapp.azure.com", # Maestro API URL + [Parameter(Mandatory=$false)][string] $MaestroApiVersion = "2019-01-16" # Version of Maestro API to use +) + +. $PSScriptRoot\post-build-utils.ps1 + +try { + Write-Host "Installing DARC ..." + + . $PSScriptRoot\..\darc-init.ps1 + $exitCode = $LASTEXITCODE + + if ($exitCode -ne 0) { + Write-PipelineTaskError "Something failed while running 'darc-init.ps1'. Check for errors above. Exiting now..." + ExitWithExitCode $exitCode + } + + darc gather-drop --non-shipping ` + --continue-on-error ` + --id $BarBuildId ` + --output-dir $DropLocation ` + --bar-uri $MaestroApiEndpoint ` + --password $MaestroApiAccessToken ` + --latest-location +} +catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + ExitWithExitCode 1 +} diff --git a/eng/common/post-build/nuget-validation.ps1 b/eng/common/post-build/nuget-validation.ps1 index 1bdced1e30..78ed0d540f 100644 --- a/eng/common/post-build/nuget-validation.ps1 +++ b/eng/common/post-build/nuget-validation.ps1 @@ -6,10 +6,7 @@ param( [Parameter(Mandatory=$true)][string] $ToolDestinationPath # Where the validation tool should be downloaded to ) -$ErrorActionPreference = "Stop" -Set-StrictMode -Version 2.0 - -. $PSScriptRoot\..\tools.ps1 +. $PSScriptRoot\post-build-utils.ps1 try { $url = "https://raw.githubusercontent.com/NuGet/NuGetGallery/jver-verify/src/VerifyMicrosoftPackage/verify.ps1" diff --git a/eng/common/post-build/post-build-utils.ps1 b/eng/common/post-build/post-build-utils.ps1 new file mode 100644 index 0000000000..551ae113f8 --- /dev/null +++ b/eng/common/post-build/post-build-utils.ps1 @@ -0,0 +1,90 @@ +# Most of the functions in this file require the variables `MaestroApiEndPoint`, +# `MaestroApiVersion` and `MaestroApiAccessToken` to be globally available. + +$ErrorActionPreference = "Stop" +Set-StrictMode -Version 2.0 + +# `tools.ps1` checks $ci to perform some actions. Since the post-build +# scripts don't necessarily execute in the same agent that run the +# build.ps1/sh script this variable isn't automatically set. +$ci = $true +. $PSScriptRoot\..\tools.ps1 + +function Create-MaestroApiRequestHeaders([string]$ContentType = "application/json") { + Validate-MaestroVars + + $headers = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' + $headers.Add('Accept', $ContentType) + $headers.Add('Authorization',"Bearer $MaestroApiAccessToken") + return $headers +} + +function Get-MaestroChannel([int]$ChannelId) { + Validate-MaestroVars + + $apiHeaders = Create-MaestroApiRequestHeaders + $apiEndpoint = "$MaestroApiEndPoint/api/channels/${ChannelId}?api-version=$MaestroApiVersion" + + $result = try { Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } + return $result +} + +function Get-MaestroBuild([int]$BuildId) { + Validate-MaestroVars + + $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken + $apiEndpoint = "$MaestroApiEndPoint/api/builds/${BuildId}?api-version=$MaestroApiVersion" + + $result = try { return Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } + return $result +} + +function Get-MaestroSubscriptions([string]$SourceRepository, [int]$ChannelId) { + Validate-MaestroVars + + $SourceRepository = [System.Web.HttpUtility]::UrlEncode($SourceRepository) + $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken + $apiEndpoint = "$MaestroApiEndPoint/api/subscriptions?sourceRepository=$SourceRepository&channelId=$ChannelId&api-version=$MaestroApiVersion" + + $result = try { Invoke-WebRequest -Method Get -Uri $apiEndpoint -Headers $apiHeaders | ConvertFrom-Json } catch { Write-Host "Error: $_" } + return $result +} + +function Trigger-Subscription([string]$SubscriptionId) { + Validate-MaestroVars + + $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken + $apiEndpoint = "$MaestroApiEndPoint/api/subscriptions/$SubscriptionId/trigger?api-version=$MaestroApiVersion" + Invoke-WebRequest -Uri $apiEndpoint -Headers $apiHeaders -Method Post | Out-Null +} + +function Assign-BuildToChannel([int]$BuildId, [int]$ChannelId) { + Validate-MaestroVars + + $apiHeaders = Create-MaestroApiRequestHeaders -AuthToken $MaestroApiAccessToken + $apiEndpoint = "$MaestroApiEndPoint/api/channels/${ChannelId}/builds/${BuildId}?api-version=$MaestroApiVersion" + Invoke-WebRequest -Method Post -Uri $apiEndpoint -Headers $apiHeaders | Out-Null +} + +function Validate-MaestroVars { + try { + Get-Variable MaestroApiEndPoint -Scope Global | Out-Null + Get-Variable MaestroApiVersion -Scope Global | Out-Null + Get-Variable MaestroApiAccessToken -Scope Global | Out-Null + + if (!($MaestroApiEndPoint -Match "^http[s]?://maestro-(int|prod).westus2.cloudapp.azure.com$")) { + Write-PipelineTaskError "MaestroApiEndPoint is not a valid Maestro URL. '$MaestroApiEndPoint'" + ExitWithExitCode 1 + } + + if (!($MaestroApiVersion -Match "^[0-9]{4}-[0-9]{2}-[0-9]{2}$")) { + Write-PipelineTaskError "MaestroApiVersion does not match a version string in the format yyyy-MM-DD. '$MaestroApiVersion'" + ExitWithExitCode 1 + } + } + catch { + Write-PipelineTaskError "Error: Variables `MaestroApiEndPoint`, `MaestroApiVersion` and `MaestroApiAccessToken` are required while using this script." + Write-Host $_ + ExitWithExitCode 1 + } +} diff --git a/eng/common/post-build/promote-build.ps1 b/eng/common/post-build/promote-build.ps1 index 84a608fa56..e5ae85f251 100644 --- a/eng/common/post-build/promote-build.ps1 +++ b/eng/common/post-build/promote-build.ps1 @@ -1,30 +1,25 @@ param( [Parameter(Mandatory=$true)][int] $BuildId, [Parameter(Mandatory=$true)][int] $ChannelId, - [Parameter(Mandatory=$true)][string] $BarToken, - [string] $MaestroEndpoint = "https://maestro-prod.westus2.cloudapp.azure.com", - [string] $ApiVersion = "2019-01-16" + [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, + [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = "https://maestro-prod.westus2.cloudapp.azure.com", + [Parameter(Mandatory=$false)][string] $MaestroApiVersion = "2019-01-16" ) -$ErrorActionPreference = "Stop" -Set-StrictMode -Version 2.0 - -. $PSScriptRoot\..\tools.ps1 - -function Get-Headers([string]$accept, [string]$barToken) { - $headers = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' - $headers.Add('Accept',$accept) - $headers.Add('Authorization',"Bearer $barToken") - return $headers -} +. $PSScriptRoot\post-build-utils.ps1 try { - $maestroHeaders = Get-Headers 'application/json' $BarToken + # Check that the channel we are going to promote the build to exist + $channelInfo = Get-MaestroChannel -ChannelId $ChannelId + + if (!$channelInfo) { + Write-Host "Channel with BAR ID $ChannelId was not found in BAR!" + ExitWithExitCode 1 + } # Get info about which channels the build has already been promoted to - $getBuildApiEndpoint = "$MaestroEndpoint/api/builds/${BuildId}?api-version=$ApiVersion" - $buildInfo = Invoke-WebRequest -Method Get -Uri $getBuildApiEndpoint -Headers $maestroHeaders | ConvertFrom-Json - + $buildInfo = Get-MaestroBuild -BuildId $BuildId + if (!$buildInfo) { Write-Host "Build with BAR ID $BuildId was not found in BAR!" ExitWithExitCode 1 @@ -40,10 +35,10 @@ try { } } - Write-Host "Build not present in channel $ChannelId. Promoting build ... " + Write-Host "Promoting build '$BuildId' to channel '$ChannelId'." + + Assign-BuildToChannel -BuildId $BuildId -ChannelId $ChannelId - $promoteBuildApiEndpoint = "$maestroEndpoint/api/channels/${ChannelId}/builds/${BuildId}?api-version=$ApiVersion" - Invoke-WebRequest -Method Post -Uri $promoteBuildApiEndpoint -Headers $maestroHeaders Write-Host "done." } catch { diff --git a/eng/common/post-build/setup-maestro-vars.ps1 b/eng/common/post-build/setup-maestro-vars.ps1 new file mode 100644 index 0000000000..d7f64dc63c --- /dev/null +++ b/eng/common/post-build/setup-maestro-vars.ps1 @@ -0,0 +1,26 @@ +param( + [Parameter(Mandatory=$true)][string] $ReleaseConfigsPath # Full path to ReleaseConfigs.txt asset +) + +. $PSScriptRoot\post-build-utils.ps1 + +try { + $Content = Get-Content $ReleaseConfigsPath + + $BarId = $Content | Select -Index 0 + + $Channels = "" + $Content | Select -Index 1 | ForEach-Object { $Channels += "$_ ," } + + $IsStableBuild = $Content | Select -Index 2 + + Write-PipelineSetVariable -Name 'BARBuildId' -Value $BarId + Write-PipelineSetVariable -Name 'InitialChannels' -Value "$Channels" + Write-PipelineSetVariable -Name 'IsStableBuild' -Value $IsStableBuild +} +catch { + Write-Host $_ + Write-Host $_.Exception + Write-Host $_.ScriptStackTrace + ExitWithExitCode 1 +} diff --git a/eng/common/post-build/sourcelink-validation.ps1 b/eng/common/post-build/sourcelink-validation.ps1 index 8abd684e9e..41e01ae6e6 100644 --- a/eng/common/post-build/sourcelink-validation.ps1 +++ b/eng/common/post-build/sourcelink-validation.ps1 @@ -6,10 +6,7 @@ param( [Parameter(Mandatory=$true)][string] $SourcelinkCliVersion # Version of SourceLink CLI to use ) -$ErrorActionPreference = "Stop" -Set-StrictMode -Version 2.0 - -. $PSScriptRoot\..\tools.ps1 +. $PSScriptRoot\post-build-utils.ps1 # Cache/HashMap (File -> Exist flag) used to consult whether a file exist # in the repository at a specific commit point. This is populated by inserting @@ -200,21 +197,27 @@ function ValidateSourceLinkLinks { } } -function CheckExitCode ([string]$stage) { - $exitCode = $LASTEXITCODE - if ($exitCode -ne 0) { - Write-PipelineTaskError "Something failed while '$stage'. Check for errors above. Exiting now..." - ExitWithExitCode $exitCode +function InstallSourcelinkCli { + $sourcelinkCliPackageName = "sourcelink" + + $dotnetRoot = InitializeDotNetCli -install:$true + $dotnet = "$dotnetRoot\dotnet.exe" + $toolList = & "$dotnet" tool list --global + + if (($toolList -like "*$sourcelinkCliPackageName*") -and ($toolList -like "*$sourcelinkCliVersion*")) { + Write-Host "SourceLink CLI version $sourcelinkCliVersion is already installed." + } + else { + Write-Host "Installing SourceLink CLI version $sourcelinkCliVersion..." + Write-Host "You may need to restart your command window if this is the first dotnet tool you have installed." + & "$dotnet" tool install $sourcelinkCliPackageName --version $sourcelinkCliVersion --verbosity "minimal" --global } } try { - Write-Host "Installing SourceLink CLI..." - Get-Location - . $PSScriptRoot\sourcelink-cli-init.ps1 -sourcelinkCliVersion $SourcelinkCliVersion - CheckExitCode "Running sourcelink-cli-init" + InstallSourcelinkCli - Measure-Command { ValidateSourceLinkLinks } + ValidateSourceLinkLinks } catch { Write-Host $_ diff --git a/eng/common/post-build/symbols-validation.ps1 b/eng/common/post-build/symbols-validation.ps1 index 69456854e0..d5ec51b150 100644 --- a/eng/common/post-build/symbols-validation.ps1 +++ b/eng/common/post-build/symbols-validation.ps1 @@ -4,10 +4,7 @@ param( [Parameter(Mandatory=$true)][string] $DotnetSymbolVersion # Version of dotnet symbol to use ) -$ErrorActionPreference = "Stop" -Set-StrictMode -Version 2.0 - -. $PSScriptRoot\..\tools.ps1 +. $PSScriptRoot\post-build-utils.ps1 Add-Type -AssemblyName System.IO.Compression.FileSystem @@ -162,19 +159,25 @@ function CheckSymbolsAvailable { } } -function CheckExitCode ([string]$stage) { - $exitCode = $LASTEXITCODE - if ($exitCode -ne 0) { - Write-PipelineTaskError "Something failed while '$stage'. Check for errors above. Exiting now..." - ExitWithExitCode $exitCode +function Installdotnetsymbol { + $dotnetsymbolPackageName = "dotnet-symbol" + + $dotnetRoot = InitializeDotNetCli -install:$true + $dotnet = "$dotnetRoot\dotnet.exe" + $toolList = & "$dotnet" tool list --global + + if (($toolList -like "*$dotnetsymbolPackageName*") -and ($toolList -like "*$dotnetsymbolVersion*")) { + Write-Host "dotnet-symbol version $dotnetsymbolVersion is already installed." + } + else { + Write-Host "Installing dotnet-symbol version $dotnetsymbolVersion..." + Write-Host "You may need to restart your command window if this is the first dotnet tool you have installed." + & "$dotnet" tool install $dotnetsymbolPackageName --version $dotnetsymbolVersion --verbosity "minimal" --global } } try { - Write-Host "Installing dotnet symbol ..." - Get-Location - . $PSScriptRoot\dotnetsymbol-init.ps1 -dotnetsymbolVersion $DotnetSymbolVersion - CheckExitCode "Running dotnetsymbol-init" + Installdotnetsymbol CheckSymbolsAvailable } diff --git a/eng/common/post-build/trigger-subscriptions.ps1 b/eng/common/post-build/trigger-subscriptions.ps1 index 1a91dab037..926d5b4551 100644 --- a/eng/common/post-build/trigger-subscriptions.ps1 +++ b/eng/common/post-build/trigger-subscriptions.ps1 @@ -1,33 +1,20 @@ -param( +param( [Parameter(Mandatory=$true)][string] $SourceRepo, [Parameter(Mandatory=$true)][int] $ChannelId, - [string] $MaestroEndpoint = "https://maestro-prod.westus2.cloudapp.azure.com", - [string] $BarToken, - [string] $ApiVersion = "2019-01-16" + [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken, + [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = "https://maestro-prod.westus2.cloudapp.azure.com", + [Parameter(Mandatory=$false)][string] $MaestroApiVersion = "2019-01-16" ) -$ErrorActionPreference = "Stop" -Set-StrictMode -Version 2.0 - -. $PSScriptRoot\..\tools.ps1 - -function Get-Headers([string]$accept, [string]$barToken) { - $headers = New-Object 'System.Collections.Generic.Dictionary[[String],[String]]' - $headers.Add('Accept',$accept) - $headers.Add('Authorization',"Bearer $barToken") - return $headers -} +. $PSScriptRoot\post-build-utils.ps1 # Get all the $SourceRepo subscriptions $normalizedSourceRepo = $SourceRepo.Replace('dnceng@', '') -$getSubscriptionsApiEndpoint = "$maestroEndpoint/api/subscriptions?sourceRepository=$normalizedSourceRepo&api-version=$apiVersion" -$headers = Get-Headers 'application/json' $barToken - -$subscriptions = Invoke-WebRequest -Uri $getSubscriptionsApiEndpoint -Headers $headers | ConvertFrom-Json +$subscriptions = Get-MaestroSubscriptions -SourceRepository $normalizedSourceRepo -ChannelId $ChannelId if (!$subscriptions) { Write-Host "No subscriptions found for source repo '$normalizedSourceRepo' in channel '$ChannelId'" - return + ExitWithExitCode 0 } $subscriptionsToTrigger = New-Object System.Collections.Generic.List[string] @@ -36,21 +23,18 @@ $failedTriggeredSubscription = $false # Get all enabled subscriptions that need dependency flow on 'everyBuild' foreach ($subscription in $subscriptions) { if ($subscription.enabled -and $subscription.policy.updateFrequency -like 'everyBuild' -and $subscription.channel.id -eq $ChannelId) { - Write-Host "$subscription.id" + Write-Host "Should trigger this subscription: $subscription.id" [void]$subscriptionsToTrigger.Add($subscription.id) } } foreach ($subscriptionToTrigger in $subscriptionsToTrigger) { try { - $triggerSubscriptionApiEndpoint = "$maestroEndpoint/api/subscriptions/$subscriptionToTrigger/trigger?api-version=$apiVersion" - $headers = Get-Headers 'application/json' $BarToken - - Write-Host "Triggering subscription '$subscriptionToTrigger'..." + Write-Host "Triggering subscription '$subscriptionToTrigger'." - Invoke-WebRequest -Uri $triggerSubscriptionApiEndpoint -Headers $headers -Method Post + Trigger-Subscription -SubscriptionId $subscriptionToTrigger - Write-Host "Subscription '$subscriptionToTrigger' triggered!" + Write-Host "done." } catch { @@ -61,9 +45,13 @@ foreach ($subscriptionToTrigger in $subscriptionsToTrigger) { } } -if ($failedTriggeredSubscription) { +if ($subscriptionsToTrigger.Count -eq 0) { + Write-Host "No subscription matched source repo '$normalizedSourceRepo' and channel ID '$ChannelId'." +} +elseif ($failedTriggeredSubscription) { Write-Host "At least one subscription failed to be triggered..." ExitWithExitCode 1 } - -Write-Host "All subscriptions were triggered successfully!" +else { + Write-Host "All subscriptions were triggered successfully!" +} diff --git a/eng/common/sdl/packages.config b/eng/common/sdl/packages.config index fb9b712863..3f97ac2f16 100644 --- a/eng/common/sdl/packages.config +++ b/eng/common/sdl/packages.config @@ -1,4 +1,4 @@ - + diff --git a/eng/common/templates/job/execute-sdl.yml b/eng/common/templates/job/execute-sdl.yml index 5837f3d56d..f657a4dc91 100644 --- a/eng/common/templates/job/execute-sdl.yml +++ b/eng/common/templates/job/execute-sdl.yml @@ -46,7 +46,7 @@ jobs: continueOnError: ${{ parameters.continueOnError }} - ${{ if eq(parameters.overrideParameters, '') }}: - powershell: eng/common/sdl/execute-all-sdl-tools.ps1 - -GuardianPackageName Microsoft.Guardian.Cli.0.6.0 + -GuardianPackageName Microsoft.Guardian.Cli.0.7.1 -NugetPackageDirectory $(Build.SourcesDirectory)\.packages -AzureDevOpsAccessToken $(dn-bot-dotnet-build-rw-code-rw) ${{ parameters.additionalParameters }} diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index 1814e0ab61..8db456bb7f 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -37,6 +37,9 @@ parameters: # Optional: Enable publishing to the build asset registry enablePublishBuildAssets: false + # Optional: Prevent gather/push manifest from executing when using publishing pipelines + enablePublishUsingPipelines: false + # Optional: Include PublishTestResults task enablePublishTestResults: false @@ -187,7 +190,7 @@ jobs: continueOnError: true condition: always() - - ${{ if and(eq(parameters.enablePublishBuildAssets, true), ne(variables['_PublishUsingPipelines'], 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: + - ${{ if and(eq(parameters.enablePublishBuildAssets, true), ne(parameters.enablePublishUsingPipelines, 'true'), eq(parameters.runAsPublic, 'false'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: - task: CopyFiles@2 displayName: Gather Asset Manifests inputs: @@ -195,6 +198,7 @@ jobs: TargetFolder: '$(Build.StagingDirectory)/AssetManifests' continueOnError: ${{ parameters.continueOnError }} condition: and(succeeded(), eq(variables['_DotNetPublishToBlobFeed'], 'true')) + - task: PublishBuildArtifacts@1 displayName: Push Asset Manifests inputs: diff --git a/eng/common/templates/post-build/channels/internal-servicing.yml b/eng/common/templates/post-build/channels/internal-servicing.yml index 648e854e0e..dc065ab308 100644 --- a/eng/common/templates/post-build/channels/internal-servicing.yml +++ b/eng/common/templates/post-build/channels/internal-servicing.yml @@ -13,7 +13,7 @@ stages: - job: displayName: Symbol Publishing dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.InternalServicing_30_Channel_Id) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.InternalServicing_30_Channel_Id)) variables: - group: DotNet-Symbol-Server-Pats pool: @@ -41,13 +41,12 @@ stages: dependsOn: setupMaestroVars variables: - group: DotNet-Blob-Feed - - group: Publish-Build-Assets - group: AzureDevOps-Artifact-Feeds-Pats - name: BARBuildId value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - name: IsStableBuild value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.InternalServicing_30_Channel_Id) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.InternalServicing_30_Channel_Id)) pool: vmImage: 'windows-2019' steps: @@ -87,8 +86,8 @@ stages: /p:StaticInternalFeed=$(dotnetfeed-internal-nonstable-feed-url) /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' - /p:BuildAssetRegistryToken='$(MaestroAccessToken)' + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' /p:BlobBasePath='$(Build.ArtifactStagingDirectory)\BlobArtifacts' /p:PackageBasePath='$(Build.ArtifactStagingDirectory)\PackageArtifacts' @@ -127,7 +126,7 @@ stages: - job: displayName: Symbol Availability dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.InternalServicing_30_Channel_Id) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.InternalServicing_30_Channel_Id)) pool: vmImage: 'windows-2019' steps: @@ -143,29 +142,6 @@ stages: filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1 arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion) - - job: - displayName: Gather Drop - dependsOn: setupMaestroVars - variables: - BARBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.InternalServicing_30_Channel_Id) - pool: - vmImage: 'windows-2019' - steps: - - task: PowerShell@2 - displayName: Setup Darc CLI - inputs: - targetType: filePath - filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1' - - - task: PowerShell@2 - displayName: Run Darc gather-drop - inputs: - targetType: inline - script: | - darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ --password $(MaestroAccessToken) --latest-location - enabled: false - - template: ../promote-build.yml parameters: ChannelId: ${{ variables.InternalServicing_30_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/netcore-dev-5.yml b/eng/common/templates/post-build/channels/netcore-dev-5.yml new file mode 100644 index 0000000000..f2b0cfb269 --- /dev/null +++ b/eng/common/templates/post-build/channels/netcore-dev-5.yml @@ -0,0 +1,148 @@ +parameters: + enableSymbolValidation: true + +stages: +- stage: NetCore_Dev5_Publish + dependsOn: validate + variables: + - template: ../common-variables.yml + displayName: .NET Core 5 Dev Channel + jobs: + - template: ../setup-maestro-vars.yml + + - job: + displayName: Symbol Publishing + dependsOn: setupMaestroVars + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_5_Dev_Channel_Id)) + variables: + - group: DotNet-Symbol-Server-Pats + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Artifacts + inputs: + downloadType: specific files + matchingPattern: "*Artifacts*" + + - task: PowerShell@2 + displayName: Publish + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet + /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) + /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) + /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/' + /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' + /p:Configuration=Release + + - job: + displayName: Publish Assets + dependsOn: setupMaestroVars + variables: + - group: DotNet-Blob-Feed + - group: AzureDevOps-Artifact-Feeds-Pats + - name: BARBuildId + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] + - name: IsStableBuild + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_5_Dev_Channel_Id)) + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: current + artifactName: PackageArtifacts + + - task: DownloadBuildArtifacts@0 + displayName: Download Blob Artifacts + inputs: + buildType: current + artifactName: BlobArtifacts + + - task: DownloadBuildArtifacts@0 + displayName: Download Asset Manifests + inputs: + buildType: current + artifactName: AssetManifests + + - task: PowerShell@2 + displayName: Add Assets Location + env: + AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-unviersal-packages-rw) + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet + /p:ChannelId=$(NetCore_5_Dev_Channel_Id) + /p:ArtifactsCategory=$(_DotNetArtifactsCategory) + /p:IsStableBuild=$(IsStableBuild) + /p:IsInternalBuild=$(IsInternalBuild) + /p:RepositoryName=$(Build.Repository.Name) + /p:CommitSha=$(Build.SourceVersion) + /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe + /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' + /p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' + /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' + /p:BARBuildId=$(BARBuildId) + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' + /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' + /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' + /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' + /p:Configuration=Release + + - task: NuGetCommand@2 + displayName: Publish Packages to AzDO Feed + condition: contains(variables['TargetAzDOFeed'], 'pkgs.visualstudio.com') + inputs: + command: push + vstsFeed: $(AzDoFeedName) + packagesToPush: $(Build.ArtifactStagingDirectory)\PackageArtifacts\*.nupkg + publishVstsFeed: $(AzDoFeedName) + + - task: PowerShell@2 + displayName: Publish Blobs to AzDO Feed + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-blobs-to-azdo.ps1 + arguments: -FeedName $(AzDoFeedName) + -SourceFolderCollection $(Build.ArtifactStagingDirectory)/BlobArtifacts/ + -PersonalAccessToken $(dn-bot-dnceng-unviersal-packages-rw) + enabled: false + + +- stage: NetCore_Dev5_PublishValidation + displayName: Publish Validation + variables: + - template: ../common-variables.yml + jobs: + - template: ../setup-maestro-vars.yml + + - ${{ if eq(parameters.enableSymbolValidation, 'true') }}: + - job: + displayName: Symbol Availability + dependsOn: setupMaestroVars + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_5_Dev_Channel_Id)) + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: current + artifactName: PackageArtifacts + + - task: PowerShell@2 + displayName: Check Symbol Availability + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1 + arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion) + + - template: ../darc-gather-drop.yml + parameters: + ChannelId: ${{ variables.NetCore_5_Dev_Channel_Id }} + + - template: ../promote-build.yml + parameters: + ChannelId: ${{ variables.NetCore_5_Dev_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/netcore-tools-latest.yml b/eng/common/templates/post-build/channels/netcore-tools-latest.yml new file mode 100644 index 0000000000..fd6c09b227 --- /dev/null +++ b/eng/common/templates/post-build/channels/netcore-tools-latest.yml @@ -0,0 +1,148 @@ +parameters: + enableSymbolValidation: true + +stages: +- stage: NetCore_Tools_Latest_Publish + dependsOn: validate + variables: + - template: ../common-variables.yml + displayName: .NET Tools - Latest + jobs: + - template: ../setup-maestro-vars.yml + + - job: + displayName: Symbol Publishing + dependsOn: setupMaestroVars + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_Tools_Latest_Channel_Id)) + variables: + - group: DotNet-Symbol-Server-Pats + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Artifacts + inputs: + downloadType: specific files + matchingPattern: "*Artifacts*" + + - task: PowerShell@2 + displayName: Publish + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task PublishToSymbolServers -restore -msbuildEngine dotnet + /p:DotNetSymbolServerTokenMsdl=$(microsoft-symbol-server-pat) + /p:DotNetSymbolServerTokenSymWeb=$(symweb-symbol-server-pat) + /p:PDBArtifactsDirectory='$(Build.ArtifactStagingDirectory)/PDBArtifacts/' + /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' + /p:Configuration=Release + + - job: + displayName: Publish Assets + dependsOn: setupMaestroVars + variables: + - group: DotNet-Blob-Feed + - group: AzureDevOps-Artifact-Feeds-Pats + - name: BARBuildId + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] + - name: IsStableBuild + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_Tools_Latest_Channel_Id)) + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: current + artifactName: PackageArtifacts + + - task: DownloadBuildArtifacts@0 + displayName: Download Blob Artifacts + inputs: + buildType: current + artifactName: BlobArtifacts + + - task: DownloadBuildArtifacts@0 + displayName: Download Asset Manifests + inputs: + buildType: current + artifactName: AssetManifests + + - task: PowerShell@2 + displayName: Add Assets Location + env: + AZURE_DEVOPS_EXT_PAT: $(dn-bot-dnceng-unviersal-packages-rw) + inputs: + filePath: eng\common\sdk-task.ps1 + arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet + /p:ChannelId=$(NetCore_Tools_Latest_Channel_Id) + /p:ArtifactsCategory=$(_DotNetArtifactsCategory) + /p:IsStableBuild=$(IsStableBuild) + /p:IsInternalBuild=$(IsInternalBuild) + /p:RepositoryName=$(Build.Repository.Name) + /p:CommitSha=$(Build.SourceVersion) + /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe + /p:AzdoTargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' + /p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' + /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' + /p:BARBuildId=$(BARBuildId) + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' + /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' + /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' + /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' + /p:Configuration=Release + + - task: NuGetCommand@2 + displayName: Publish Packages to AzDO Feed + condition: contains(variables['TargetAzDOFeed'], 'pkgs.visualstudio.com') + inputs: + command: push + vstsFeed: $(AzDoFeedName) + packagesToPush: $(Build.ArtifactStagingDirectory)\PackageArtifacts\*.nupkg + publishVstsFeed: $(AzDoFeedName) + + - task: PowerShell@2 + displayName: Publish Blobs to AzDO Feed + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/publish-blobs-to-azdo.ps1 + arguments: -FeedName $(AzDoFeedName) + -SourceFolderCollection $(Build.ArtifactStagingDirectory)/BlobArtifacts/ + -PersonalAccessToken $(dn-bot-dnceng-unviersal-packages-rw) + enabled: false + + +- stage: NetCore_Tools_Latest_PublishValidation + displayName: Publish Validation + variables: + - template: ../common-variables.yml + jobs: + - template: ../setup-maestro-vars.yml + + - ${{ if eq(parameters.enableSymbolValidation, 'true') }}: + - job: + displayName: Symbol Availability + dependsOn: setupMaestroVars + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.NetCore_Tools_Latest_Channel_Id)) + pool: + vmImage: 'windows-2019' + steps: + - task: DownloadBuildArtifacts@0 + displayName: Download Package Artifacts + inputs: + buildType: current + artifactName: PackageArtifacts + + - task: PowerShell@2 + displayName: Check Symbol Availability + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1 + arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion) + + - template: ../darc-gather-drop.yml + parameters: + ChannelId: ${{ variables.NetCore_Tools_Latest_Channel_Id }} + + - template: ../promote-build.yml + parameters: + ChannelId: ${{ variables.NetCore_Tools_Latest_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/public-dev-release.yml b/eng/common/templates/post-build/channels/public-dev-release.yml index bdc631016b..771dcf4ef8 100644 --- a/eng/common/templates/post-build/channels/public-dev-release.yml +++ b/eng/common/templates/post-build/channels/public-dev-release.yml @@ -13,7 +13,7 @@ stages: - job: displayName: Symbol Publishing dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicDevRelease_30_Channel_Id) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicDevRelease_30_Channel_Id)) variables: - group: DotNet-Symbol-Server-Pats pool: @@ -41,13 +41,12 @@ stages: dependsOn: setupMaestroVars variables: - group: DotNet-Blob-Feed - - group: Publish-Build-Assets - group: AzureDevOps-Artifact-Feeds-Pats - name: BARBuildId value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - name: IsStableBuild value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicDevRelease_30_Channel_Id) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicDevRelease_30_Channel_Id)) pool: vmImage: 'windows-2019' steps: @@ -77,7 +76,7 @@ stages: filePath: eng\common\sdk-task.ps1 arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet /p:ChannelId=$(PublicDevRelease_30_Channel_Id) - /p:ArtifactsCategory=.NetCore + /p:ArtifactsCategory=$(_DotNetArtifactsCategory) /p:IsStableBuild=$(IsStableBuild) /p:IsInternalBuild=$(IsInternalBuild) /p:RepositoryName=$(Build.Repository.Name) @@ -87,8 +86,8 @@ stages: /p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' - /p:BuildAssetRegistryToken='$(MaestroAccessToken)' + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' /p:BlobBasePath='$(Build.ArtifactStagingDirectory)/BlobArtifacts/' /p:PackageBasePath='$(Build.ArtifactStagingDirectory)/PackageArtifacts/' @@ -124,7 +123,7 @@ stages: - job: displayName: Symbol Availability dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicDevRelease_30_Channel_Id) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicDevRelease_30_Channel_Id)) pool: vmImage: 'windows-2019' steps: @@ -140,27 +139,9 @@ stages: filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1 arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion) - - job: - displayName: Gather Drop - dependsOn: setupMaestroVars - variables: - BARBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicDevRelease_30_Channel_Id) - pool: - vmImage: 'windows-2019' - steps: - - task: PowerShell@2 - displayName: Setup Darc CLI - inputs: - targetType: filePath - filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1' - - - task: PowerShell@2 - displayName: Run Darc gather-drop - inputs: - targetType: inline - script: | - darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ --password $(MaestroAccessToken) --latest-location + - template: ../darc-gather-drop.yml + parameters: + ChannelId: ${{ variables.PublicDevRelease_30_Channel_Id }} - template: ../promote-build.yml parameters: diff --git a/eng/common/templates/post-build/channels/public-release.yml b/eng/common/templates/post-build/channels/public-release.yml index f6a7efdfe9..00108bd3f8 100644 --- a/eng/common/templates/post-build/channels/public-release.yml +++ b/eng/common/templates/post-build/channels/public-release.yml @@ -13,7 +13,7 @@ stages: - job: displayName: Symbol Publishing dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicRelease_30_Channel_Id) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicRelease_30_Channel_Id)) variables: - group: DotNet-Symbol-Server-Pats pool: @@ -41,13 +41,12 @@ stages: dependsOn: setupMaestroVars variables: - group: DotNet-Blob-Feed - - group: Publish-Build-Assets - group: AzureDevOps-Artifact-Feeds-Pats - name: BARBuildId value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - name: IsStableBuild value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicRelease_30_Channel_Id) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicRelease_30_Channel_Id)) pool: vmImage: 'windows-2019' steps: @@ -87,8 +86,8 @@ stages: /p:StaticInternalFeed=$(dotnetfeed-internal-nonstable-feed-url) /p:NugetPath=$(Agent.BuildDirectory)\Nuget\NuGet.exe /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' - /p:BuildAssetRegistryToken='$(MaestroAccessToken)' + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' /p:BlobBasePath='$(Build.ArtifactStagingDirectory)\BlobArtifacts' /p:PackageBasePath='$(Build.ArtifactStagingDirectory)\PackageArtifacts' @@ -127,7 +126,7 @@ stages: - job: displayName: Symbol Availability dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicRelease_30_Channel_Id) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicRelease_30_Channel_Id)) pool: vmImage: 'windows-2019' steps: @@ -143,29 +142,6 @@ stages: filePath: $(Build.SourcesDirectory)/eng/common/post-build/symbols-validation.ps1 arguments: -InputPath $(Build.ArtifactStagingDirectory)/PackageArtifacts/ -ExtractPath $(Agent.BuildDirectory)/Temp/ -DotnetSymbolVersion $(SymbolToolVersion) - - job: - displayName: Gather Drop - dependsOn: setupMaestroVars - variables: - BARBuildId: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicRelease_30_Channel_Id) - pool: - vmImage: 'windows-2019' - steps: - - task: PowerShell@2 - displayName: Setup Darc CLI - inputs: - targetType: filePath - filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1' - - - task: PowerShell@2 - displayName: Run Darc gather-drop - inputs: - targetType: inline - script: | - darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com/ --password $(MaestroAccessToken) --latest-location - enabled: false - - template: ../promote-build.yml parameters: ChannelId: ${{ variables.PublicRelease_30_Channel_Id }} diff --git a/eng/common/templates/post-build/channels/public-validation-release.yml b/eng/common/templates/post-build/channels/public-validation-release.yml index f12f402ad9..f64184da9f 100644 --- a/eng/common/templates/post-build/channels/public-validation-release.yml +++ b/eng/common/templates/post-build/channels/public-validation-release.yml @@ -12,13 +12,12 @@ stages: dependsOn: setupMaestroVars variables: - group: DotNet-Blob-Feed - - group: Publish-Build-Assets - group: AzureDevOps-Artifact-Feeds-Pats - name: BARBuildId value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - name: IsStableBuild value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.IsStableBuild'] ] - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicValidationRelease_30_Channel_Id) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', variables.PublicValidationRelease_30_Channel_Id)) pool: vmImage: 'windows-2019' steps: @@ -48,7 +47,7 @@ stages: filePath: eng\common\sdk-task.ps1 arguments: -task PublishArtifactsInManifest -restore -msbuildEngine dotnet /p:ChannelId=$(PublicValidationRelease_30_Channel_Id) - /p:ArtifactsCategory=.NetCoreValidation + /p:ArtifactsCategory=$(_DotNetValidationArtifactsCategory) /p:IsStableBuild=$(IsStableBuild) /p:IsInternalBuild=$(IsInternalBuild) /p:RepositoryName=$(Build.Repository.Name) @@ -58,13 +57,13 @@ stages: /p:TargetFeedPAT='$(dn-bot-dnceng-unviersal-packages-rw)' /p:AzureStorageTargetFeedPAT='$(dotnetfeed-storage-access-key-1)' /p:BARBuildId=$(BARBuildId) - /p:MaestroApiEndpoint='https://maestro-prod.westus2.cloudapp.azure.com' - /p:BuildAssetRegistryToken='$(MaestroAccessToken)' + /p:MaestroApiEndpoint='$(MaestroApiEndPoint)' + /p:BuildAssetRegistryToken='$(MaestroApiAccessToken)' /p:ManifestsBasePath='$(Build.ArtifactStagingDirectory)/AssetManifests/' /p:BlobBasePath='$(Build.ArtifactStagingDirectory)\BlobArtifacts' /p:PackageBasePath='$(Build.ArtifactStagingDirectory)\PackageArtifacts' /p:Configuration=Release - + - task: NuGetCommand@2 displayName: Publish Packages to AzDO Feed condition: contains(variables['TargetAzDOFeed'], 'pkgs.visualstudio.com') @@ -91,29 +90,9 @@ stages: jobs: - template: ../setup-maestro-vars.yml - - job: - displayName: Gather Drop - dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], variables.PublicValidationRelease_30_Channel_Id) - variables: - - name: BARBuildId - value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - - group: Publish-Build-Assets - pool: - vmImage: 'windows-2019' - steps: - - task: PowerShell@2 - displayName: Setup Darc CLI - inputs: - targetType: filePath - filePath: '$(Build.SourcesDirectory)/eng/common/darc-init.ps1' - - - task: PowerShell@2 - displayName: Run Darc gather-drop - inputs: - targetType: inline - script: | - darc gather-drop --non-shipping --continue-on-error --id $(BARBuildId) --output-dir $(Agent.BuildDirectory)/Temp/Drop/ --bar-uri https://maestro-prod.westus2.cloudapp.azure.com --password $(MaestroAccessToken) --latest-location + - template: ../darc-gather-drop.yml + parameters: + ChannelId: ${{ variables.PublicValidationRelease_30_Channel_Id }} - template: ../promote-build.yml parameters: diff --git a/eng/common/templates/post-build/common-variables.yml b/eng/common/templates/post-build/common-variables.yml index 42df4ae77e..52a74487fd 100644 --- a/eng/common/templates/post-build/common-variables.yml +++ b/eng/common/templates/post-build/common-variables.yml @@ -1,21 +1,47 @@ variables: + - group: Publish-Build-Assets + # .NET Core 3 Dev - PublicDevRelease_30_Channel_Id: 3 + - name: PublicDevRelease_30_Channel_Id + value: 3 + + # .NET Core 5 Dev + - name: NetCore_5_Dev_Channel_Id + value: 131 # .NET Tools - Validation - PublicValidationRelease_30_Channel_Id: 9 + - name: PublicValidationRelease_30_Channel_Id + value: 9 + + # .NET Tools - Latest + - name: NetCore_Tools_Latest_Channel_Id + value: 2 # .NET Core 3.0 Internal Servicing - InternalServicing_30_Channel_Id: 184 + - name: InternalServicing_30_Channel_Id + value: 184 # .NET Core 3.0 Release - PublicRelease_30_Channel_Id: 19 + - name: PublicRelease_30_Channel_Id + value: 19 # Whether the build is internal or not - IsInternalBuild: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} + - name: IsInternalBuild + value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} # Storage account name for proxy-backed feeds - ProxyBackedFeedsAccountName: dotnetfeed + - name: ProxyBackedFeedsAccountName + value: dotnetfeed - SourceLinkCLIVersion: 3.0.0 - SymbolToolVersion: 1.0.1 + # Default Maestro++ API Endpoint and API Version + - name: MaestroApiEndPoint + value: "https://maestro-prod.westus2.cloudapp.azure.com" + - name: MaestroApiAccessToken + value: $(MaestroAccessToken) + - name: MaestroApiVersion + value: "2019-01-16" + + - name: SourceLinkCLIVersion + value: 3.0.0 + - name: SymbolToolVersion + value: 1.0.1 diff --git a/eng/common/templates/post-build/darc-gather-drop.yml b/eng/common/templates/post-build/darc-gather-drop.yml new file mode 100644 index 0000000000..3268ccaa55 --- /dev/null +++ b/eng/common/templates/post-build/darc-gather-drop.yml @@ -0,0 +1,23 @@ +parameters: + ChannelId: 0 + +jobs: +- job: gatherDrop + displayName: Gather Drop + dependsOn: setupMaestroVars + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.ChannelId }})) + variables: + - name: BARBuildId + value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] + pool: + vmImage: 'windows-2019' + steps: + - task: PowerShell@2 + displayName: Darc gather-drop + inputs: + filePath: $(Build.SourcesDirectory)/eng/common/post-build/darc-gather-drop.ps1 + arguments: -BarBuildId $(BARBuildId) + -DropLocation $(Agent.BuildDirectory)/Temp/Drop/ + -MaestroApiAccessToken $(MaestroApiAccessToken) + -MaestroApiEndPoint $(MaestroApiEndPoint) + -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index daa799259c..33db50ce26 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -7,9 +7,12 @@ parameters: enable: false params: '' + # Which stages should finish execution before post-build stages start + dependsOn: [build] + stages: - stage: validate - dependsOn: build + dependsOn: ${{ parameters.dependsOn }} displayName: Validate jobs: - ${{ if eq(parameters.enableNugetValidation, 'true') }}: @@ -80,10 +83,18 @@ stages: parameters: additionalParameters: ${{ parameters.SDLValidationParameters.params }} +- template: \eng\common\templates\post-build\channels\netcore-dev-5.yml + parameters: + enableSymbolValidation: ${{ parameters.enableSymbolValidation }} + - template: \eng\common\templates\post-build\channels\public-dev-release.yml parameters: enableSymbolValidation: ${{ parameters.enableSymbolValidation }} +- template: \eng\common\templates\post-build\channels\netcore-tools-latest.yml + parameters: + enableSymbolValidation: ${{ parameters.enableSymbolValidation }} + - template: \eng\common\templates\post-build\channels\public-validation-release.yml - template: \eng\common\templates\post-build\channels\public-release.yml diff --git a/eng/common/templates/post-build/promote-build.yml b/eng/common/templates/post-build/promote-build.yml index af48b0b339..6b479c3b82 100644 --- a/eng/common/templates/post-build/promote-build.yml +++ b/eng/common/templates/post-build/promote-build.yml @@ -5,13 +5,12 @@ jobs: - job: displayName: Promote Build dependsOn: setupMaestroVars - condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], ${{ parameters.ChannelId }}) + condition: contains(dependencies.setupMaestroVars.outputs['setReleaseVars.InitialChannels'], format('[{0}]', ${{ parameters.ChannelId }})) variables: - name: BARBuildId value: $[ dependencies.setupMaestroVars.outputs['setReleaseVars.BARBuildId'] ] - name: ChannelId value: ${{ parameters.ChannelId }} - - group: Publish-Build-Assets pool: vmImage: 'windows-2019' steps: @@ -21,4 +20,6 @@ jobs: filePath: $(Build.SourcesDirectory)/eng/common/post-build/promote-build.ps1 arguments: -BuildId $(BARBuildId) -ChannelId $(ChannelId) - -BarToken $(MaestroAccessToken) + -MaestroApiAccessToken $(MaestroApiAccessToken) + -MaestroApiEndPoint $(MaestroApiEndPoint) + -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/templates/post-build/setup-maestro-vars.yml b/eng/common/templates/post-build/setup-maestro-vars.yml index f6120dc1e1..56242b068e 100644 --- a/eng/common/templates/post-build/setup-maestro-vars.yml +++ b/eng/common/templates/post-build/setup-maestro-vars.yml @@ -14,22 +14,5 @@ jobs: name: setReleaseVars displayName: Set Release Configs Vars inputs: - targetType: inline - script: | - # This is needed to make Write-PipelineSetVariable works in this context - $ci = $true - - . "$(Build.SourcesDirectory)/eng/common/tools.ps1" - - $Content = Get-Content "$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt" - - $BarId = $Content | Select -Index 0 - - $Channels = "" - $Content | Select -Index 1 | ForEach-Object { $Channels += "$_ ," } - - $IsStableBuild = $Content | Select -Index 2 - - Write-PipelineSetVariable -Name 'BARBuildId' -Value $BarId - Write-PipelineSetVariable -Name 'InitialChannels' -Value "$Channels" - Write-PipelineSetVariable -Name 'IsStableBuild' -Value $IsStableBuild + filePath: $(Build.SourcesDirectory)/eng/common/post-build/setup-maestro-vars.ps1 + arguments: -ReleaseConfigsPath '$(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt' diff --git a/eng/common/templates/post-build/trigger-subscription.yml b/eng/common/templates/post-build/trigger-subscription.yml index 65259d4e68..da669030da 100644 --- a/eng/common/templates/post-build/trigger-subscription.yml +++ b/eng/common/templates/post-build/trigger-subscription.yml @@ -8,4 +8,6 @@ steps: filePath: $(Build.SourcesDirectory)/eng/common/post-build/trigger-subscriptions.ps1 arguments: -SourceRepo $(Build.Repository.Uri) -ChannelId ${{ parameters.ChannelId }} - -BarToken $(MaestroAccessTokenInt) \ No newline at end of file + -MaestroApiAccessToken $(MaestroAccessToken) + -MaestroApiEndPoint $(MaestroApiEndPoint) + -MaestroApiVersion $(MaestroApiVersion) diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 8fe2b11ad2..9c12b1b4fd 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -39,6 +39,10 @@ # installed on the machine instead of downloading one. [bool]$useInstalledDotNetCli = if (Test-Path variable:useInstalledDotNetCli) { $useInstalledDotNetCli } else { $true } +# Enable repos to use a particular version of the on-line dotnet-install scripts. +# default URL: https://dot.net/v1/dotnet-install.ps1 +[string]$dotnetInstallScriptVersion = if (Test-Path variable:dotnetInstallScriptVersion) { $dotnetInstallScriptVersion } else { "v1" } + # True to use global NuGet cache instead of restoring packages to repository-local directory. [bool]$useGlobalNuGetCache = if (Test-Path variable:useGlobalNuGetCache) { $useGlobalNuGetCache } else { !$ci } @@ -159,7 +163,7 @@ function GetDotNetInstallScript([string] $dotnetRoot) { $installScript = Join-Path $dotnetRoot "dotnet-install.ps1" if (!(Test-Path $installScript)) { Create-Directory $dotnetRoot - Invoke-WebRequest "https://dot.net/v1/dotnet-install.ps1" -OutFile $installScript + Invoke-WebRequest "https://dot.net/$dotnetInstallScriptVersion/dotnet-install.ps1" -OutFile $installScript } return $installScript @@ -518,6 +522,9 @@ function MSBuild-Core() { if ($warnAsError) { $cmdArgs += " /warnaserror /p:TreatWarningsAsErrors=true" } + else { + $cmdArgs += " /p:TreatWarningsAsErrors=false" + } foreach ($arg in $args) { if ($arg -ne $null -and $arg.Trim() -ne "") { diff --git a/eng/common/tools.sh b/eng/common/tools.sh index 0deb01c480..3af9be6157 100755 --- a/eng/common/tools.sh +++ b/eng/common/tools.sh @@ -45,6 +45,10 @@ warn_as_error=${warn_as_error:-true} # installed on the machine instead of downloading one. use_installed_dotnet_cli=${use_installed_dotnet_cli:-true} +# Enable repos to use a particular version of the on-line dotnet-install scripts. +# default URL: https://dot.net/v1/dotnet-install.sh +dotnetInstallScriptVersion=${dotnetInstallScriptVersion:-'v1'} + # True to use global NuGet cache instead of restoring packages to repository-local directory. if [[ "$ci" == true ]]; then use_global_nuget_cache=${use_global_nuget_cache:-false} @@ -77,7 +81,7 @@ function ReadGlobalVersion { local pattern="\"$key\" *: *\"(.*)\"" if [[ ! $line =~ $pattern ]]; then - Write-PipelineTelemetryError -category 'InitializeTools' "Error: Cannot find \"$key\" in $global_json_file" + Write-PipelineTelemetryError -category 'InitializeToolset' "Error: Cannot find \"$key\" in $global_json_file" ExitWithExitCode 1 fi @@ -195,7 +199,7 @@ function InstallDotNet { function GetDotNetInstallScript { local root=$1 local install_script="$root/dotnet-install.sh" - local install_script_url="https://dot.net/v1/dotnet-install.sh" + local install_script_url="https://dot.net/$dotnetInstallScriptVersion/dotnet-install.sh" if [[ ! -a "$install_script" ]]; then mkdir -p "$root" @@ -245,7 +249,7 @@ function InitializeNativeTools() { then local nativeArgs="" if [[ "$ci" == true ]]; then - nativeArgs="-InstallDirectory $tools_dir" + nativeArgs="--installDirectory $tools_dir" fi "$_script_dir/init-tools-native.sh" $nativeArgs fi diff --git a/eng/scripts/CodeCheck.ps1 b/eng/scripts/CodeCheck.ps1 index 669b56c21f..5ed823f083 100644 --- a/eng/scripts/CodeCheck.ps1 +++ b/eng/scripts/CodeCheck.ps1 @@ -166,11 +166,6 @@ try { & dotnet run -p "$repoRoot/eng/tools/BaselineGenerator/" } - Write-Host "Re-generating Web.JS files" - Invoke-Block { - & dotnet build "$repoRoot\src\Components\Web.JS\Microsoft.AspNetCore.Components.Web.JS.npmproj" - } - Write-Host "Run git diff to check for pending changes" # Redirect stderr to stdout because PowerShell does not consistently handle output to stderr diff --git a/eng/targets/Npm.Common.targets b/eng/targets/Npm.Common.targets index c290e39756..204e14d01f 100644 --- a/eng/targets/Npm.Common.targets +++ b/eng/targets/Npm.Common.targets @@ -11,15 +11,28 @@ $([MSBuild]::NormalizeDirectory('$(BaseIntermediateOutputPath)'))$(Configuration)\ --frozen-lockfile <_BackupPackageJson>$(IntermediateOutputPath)$(MSBuildProjectName).package.json.bak + + PrepareForBuild; + ResolveProjectReferences; + _Build; + + run build + + + + + + + @@ -36,13 +49,13 @@ BuildInParallel="true" /> - + - + diff --git a/global.json b/global.json index 4f83cb7a89..64afa6336e 100644 --- a/global.json +++ b/global.json @@ -24,7 +24,7 @@ }, "msbuild-sdks": { "Yarn.MSBuild": "1.15.2", - "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19369.2", - "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19369.2" + "Microsoft.DotNet.Arcade.Sdk": "1.0.0-beta.19404.1", + "Microsoft.DotNet.Helix.Sdk": "2.0.0-beta.19404.1" } } diff --git a/src/Components/Analyzers/src/ComponentInternalUsageDiagnosticAnalzyer.cs b/src/Components/Analyzers/src/ComponentInternalUsageDiagnosticAnalzyer.cs new file mode 100644 index 0000000000..3f0c765614 --- /dev/null +++ b/src/Components/Analyzers/src/ComponentInternalUsageDiagnosticAnalzyer.cs @@ -0,0 +1,39 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using Microsoft.AspNetCore.Components.Analyzers; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.Extensions.Internal +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public class ComponentInternalUsageDiagnosticAnalyzer : DiagnosticAnalyzer + { + private readonly InternalUsageAnalyzer _inner; + + public ComponentInternalUsageDiagnosticAnalyzer() + { + // We don't have in *internal* attribute in Blazor. + _inner = new InternalUsageAnalyzer(IsInInternalNamespace, hasInternalAttribute: null, DiagnosticDescriptors.DoNotUseRenderTreeTypes); + } + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(DiagnosticDescriptors.DoNotUseRenderTreeTypes); + + public override void Initialize(AnalysisContext context) + { + _inner.Register(context); + } + + private static bool IsInInternalNamespace(ISymbol symbol) + { + if (symbol?.ContainingNamespace?.ToDisplayString() is string ns) + { + return string.Equals(ns, "Microsoft.AspNetCore.Components.RenderTree"); + } + + return false; + } + } +} diff --git a/src/Components/Analyzers/src/DiagnosticDescriptors.cs b/src/Components/Analyzers/src/DiagnosticDescriptors.cs index e0ecbce055..8eb86b3212 100644 --- a/src/Components/Analyzers/src/DiagnosticDescriptors.cs +++ b/src/Components/Analyzers/src/DiagnosticDescriptors.cs @@ -55,5 +55,14 @@ namespace Microsoft.AspNetCore.Components.Analyzers DiagnosticSeverity.Warning, isEnabledByDefault: true, description: new LocalizableResourceString(nameof(Resources.ComponentParameterShouldNotBeSetOutsideOfTheirDeclaredComponent_Description), Resources.ResourceManager, typeof(Resources))); + + public static readonly DiagnosticDescriptor DoNotUseRenderTreeTypes = new DiagnosticDescriptor( + "BL0006", + new LocalizableResourceString(nameof(Resources.DoNotUseRenderTreeTypes_Title), Resources.ResourceManager, typeof(Resources)), + new LocalizableResourceString(nameof(Resources.DoNotUseRenderTreeTypes_Description), Resources.ResourceManager, typeof(Resources)), + "Usage", + DiagnosticSeverity.Warning, + isEnabledByDefault: true, + description: new LocalizableResourceString(nameof(Resources.DoNotUseRenderTreeTypes_Description), Resources.ResourceManager, typeof(Resources))); } } diff --git a/src/Components/Analyzers/src/InternalUsageAnalyzer.cs b/src/Components/Analyzers/src/InternalUsageAnalyzer.cs new file mode 100644 index 0000000000..92b07a7ab2 --- /dev/null +++ b/src/Components/Analyzers/src/InternalUsageAnalyzer.cs @@ -0,0 +1,126 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.Extensions.Internal +{ + internal class InternalUsageAnalyzer + { + private readonly Func _isInternalNamespace; + private readonly Func _hasInternalAttribute; + private readonly DiagnosticDescriptor _descriptor; + + /// + /// Creates a new instance of . The creator should provide delegates to help determine whether + /// a given symbol is internal or not, and a to create errors. + /// + /// The delegate used to check if a symbol belongs to an internal namespace. + /// The delegate used to check if a symbol has an internal attribute. + /// + /// The used to create errors. The error message should expect a single parameter + /// used for the display name of the member. + /// + public InternalUsageAnalyzer(Func isInInternalNamespace, Func hasInternalAttribute, DiagnosticDescriptor descriptor) + { + _isInternalNamespace = isInInternalNamespace ?? new Func((_) => false); + _hasInternalAttribute = hasInternalAttribute ?? new Func((_) => false); + _descriptor = descriptor ?? throw new ArgumentNullException(nameof(descriptor)); + } + + public void Register(AnalysisContext context) + { + context.EnableConcurrentExecution(); + context.RegisterSyntaxNodeAction(AnalyzeNode, + SyntaxKind.SimpleMemberAccessExpression, + SyntaxKind.ObjectCreationExpression, + SyntaxKind.ClassDeclaration, + SyntaxKind.Parameter); + } + + private void AnalyzeNode(SyntaxNodeAnalysisContext context) + { + switch (context.Node) + { + case MemberAccessExpressionSyntax memberAccessSyntax: + { + if (context.SemanticModel.GetSymbolInfo(context.Node, context.CancellationToken).Symbol is ISymbol symbol && + symbol.ContainingAssembly != context.Compilation.Assembly) + { + var containingType = symbol.ContainingType; + + if (HasInternalAttribute(symbol)) + { + context.ReportDiagnostic(Diagnostic.Create(_descriptor, memberAccessSyntax.Name.GetLocation(), $"{containingType}.{symbol.Name}")); + return; + } + + if (IsInInternalNamespace(containingType) || HasInternalAttribute(containingType)) + { + context.ReportDiagnostic(Diagnostic.Create(_descriptor, memberAccessSyntax.Name.GetLocation(), containingType)); + return; + } + } + return; + } + + case ObjectCreationExpressionSyntax creationSyntax: + { + if (context.SemanticModel.GetSymbolInfo(context.Node, context.CancellationToken).Symbol is ISymbol symbol && + symbol.ContainingAssembly != context.Compilation.Assembly) + { + var containingType = symbol.ContainingType; + + if (HasInternalAttribute(symbol)) + { + context.ReportDiagnostic(Diagnostic.Create(_descriptor, creationSyntax.GetLocation(), containingType)); + return; + } + + if (IsInInternalNamespace(containingType) || HasInternalAttribute(containingType)) + { + context.ReportDiagnostic(Diagnostic.Create(_descriptor, creationSyntax.Type.GetLocation(), containingType)); + return; + } + } + + return; + } + + case ClassDeclarationSyntax declarationSyntax: + { + if (context.SemanticModel.GetDeclaredSymbol(declarationSyntax)?.BaseType is ISymbol symbol && + symbol.ContainingAssembly != context.Compilation.Assembly && + (IsInInternalNamespace(symbol) || HasInternalAttribute(symbol)) && + declarationSyntax.BaseList?.Types.Count > 0) + { + context.ReportDiagnostic(Diagnostic.Create(_descriptor, declarationSyntax.BaseList.Types[0].GetLocation(), symbol)); + } + + return; + } + + case ParameterSyntax parameterSyntax: + { + if (context.SemanticModel.GetDeclaredSymbol(parameterSyntax)?.Type is ISymbol symbol && + symbol.ContainingAssembly != context.Compilation.Assembly && + (IsInInternalNamespace(symbol) || HasInternalAttribute(symbol))) + { + + context.ReportDiagnostic(Diagnostic.Create(_descriptor, parameterSyntax.GetLocation(), symbol)); + } + + return; + } + } + } + + private bool HasInternalAttribute(ISymbol symbol) => _hasInternalAttribute(symbol); + + private bool IsInInternalNamespace(ISymbol symbol) => _isInternalNamespace(symbol); + } +} diff --git a/src/Components/Analyzers/src/Resources.resx b/src/Components/Analyzers/src/Resources.resx index 648adb2c3b..ed4f36c531 100644 --- a/src/Components/Analyzers/src/Resources.resx +++ b/src/Components/Analyzers/src/Resources.resx @@ -1,17 +1,17 @@ - @@ -165,4 +165,13 @@ Component parameter should not be set outside of its component. + + The types in 'Microsoft.AspNetCore.Components.RenderTree' are not recommended for use outside of the Blazor framework. These type definitions will change in future releases. + + + The type or member {0} is is not recommended for use outside of the Blazor frameworks. Types defined in 'Microsoft.AspNetCore.Components.RenderTree' will change in future releases. + + + Do not use RenderTree types + \ No newline at end of file diff --git a/src/Components/Analyzers/test/AnalyzerTestBase.cs b/src/Components/Analyzers/test/AnalyzerTestBase.cs new file mode 100644 index 0000000000..e174b4f667 --- /dev/null +++ b/src/Components/Analyzers/test/AnalyzerTestBase.cs @@ -0,0 +1,68 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Analyzer.Testing; +using Microsoft.AspNetCore.Testing; +using Microsoft.AspNetCore.Testing.xunit; +using Microsoft.CodeAnalysis; + +namespace Microsoft.AspNetCore.Components.Analyzers +{ + public abstract class AnalyzerTestBase + { + private static readonly string ProjectDirectory = GetProjectDirectory(); + + public TestSource Read(string source) + { + if (!source.EndsWith(".cs")) + { + source = source + ".cs"; + } + + var filePath = Path.Combine(ProjectDirectory, "TestFiles", GetType().Name, source); + if (!File.Exists(filePath)) + { + throw new FileNotFoundException($"TestFile {source} could not be found at {filePath}.", filePath); + } + + var fileContent = File.ReadAllText(filePath); + return TestSource.Read(fileContent); + } + + public Project CreateProject(string source) + { + if (!source.EndsWith(".cs")) + { + source = source + ".cs"; + } + + var read = Read(source); + return DiagnosticProject.Create(GetType().Assembly, new[] { read.Source, }); + } + + public Task CreateCompilationAsync(string source) + { + return CreateProject(source).GetCompilationAsync(); + } + + private static string GetProjectDirectory() + { + // On helix we use the published test files + if (SkipOnHelixAttribute.OnHelix()) + { + return AppContext.BaseDirectory; + } + + // This test code needs to be updated to support distributed testing. + // See https://github.com/aspnet/AspNetCore/issues/10422 +#pragma warning disable 0618 + var solutionDirectory = TestPathUtilities.GetSolutionRootDirectory("Components"); +#pragma warning restore 0618 + var projectDirectory = Path.Combine(solutionDirectory, "Analyzers", "test"); + return projectDirectory; + } + } +} diff --git a/src/Components/Analyzers/test/ComponentAnalyzerDiagnosticAnalyzerRunner.cs b/src/Components/Analyzers/test/ComponentAnalyzerDiagnosticAnalyzerRunner.cs new file mode 100644 index 0000000000..727f060bd4 --- /dev/null +++ b/src/Components/Analyzers/test/ComponentAnalyzerDiagnosticAnalyzerRunner.cs @@ -0,0 +1,31 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Analyzer.Testing; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.AspNetCore.Components.Analyzers +{ + internal class ComponentAnalyzerDiagnosticAnalyzerRunner : DiagnosticAnalyzerRunner + { + public ComponentAnalyzerDiagnosticAnalyzerRunner(DiagnosticAnalyzer analyzer) + { + Analyzer = analyzer; + } + + public DiagnosticAnalyzer Analyzer { get; } + + public Task GetDiagnosticsAsync(string source) + { + return GetDiagnosticsAsync(sources: new[] { source }, Analyzer, Array.Empty()); + } + + public Task GetDiagnosticsAsync(Project project) + { + return GetDiagnosticsAsync(new[] { project }, Analyzer, Array.Empty()); + } + } +} diff --git a/src/Components/Analyzers/test/ComponentInternalUsageDiagnoticsAnalyzerTest.cs b/src/Components/Analyzers/test/ComponentInternalUsageDiagnoticsAnalyzerTest.cs new file mode 100644 index 0000000000..92e2252304 --- /dev/null +++ b/src/Components/Analyzers/test/ComponentInternalUsageDiagnoticsAnalyzerTest.cs @@ -0,0 +1,60 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.AspNetCore.Analyzer.Testing; +using Microsoft.Extensions.Internal; +using Xunit; + +namespace Microsoft.AspNetCore.Components.Analyzers +{ + public class ComponentInternalUsageDiagnoticsAnalyzerTest : AnalyzerTestBase + { + public ComponentInternalUsageDiagnoticsAnalyzerTest() + { + Analyzer = new ComponentInternalUsageDiagnosticAnalyzer(); + Runner = new ComponentAnalyzerDiagnosticAnalyzerRunner(Analyzer); + } + + private ComponentInternalUsageDiagnosticAnalyzer Analyzer { get; } + private ComponentAnalyzerDiagnosticAnalyzerRunner Runner { get; } + + [Fact] + public async Task InternalUsage_FindsUseOfRenderTreeFrameAsParameter() + { + // Arrange + var source = Read("UsesRenderTreeFrameAsParameter"); + + // Act + var diagnostics = await Runner.GetDiagnosticsAsync(source.Source); + + // Assert + Assert.Collection( + diagnostics, + diagnostic => + { + Assert.Same(DiagnosticDescriptors.DoNotUseRenderTreeTypes, diagnostic.Descriptor); + AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); + }); + } + + [Fact] + public async Task InternalUsage_FindsUseOfRenderTreeType() + { + // Arrange + var source = Read("UsesRenderTreeFrameTypeAsLocal"); + + // Act + var diagnostics = await Runner.GetDiagnosticsAsync(source.Source); + + // Assert + Assert.Collection( + diagnostics, + diagnostic => + { + Assert.Same(DiagnosticDescriptors.DoNotUseRenderTreeTypes, diagnostic.Descriptor); + AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location); + }); + } + } +} diff --git a/src/Components/Analyzers/test/Microsoft.AspNetCore.Components.Analyzers.Tests.csproj b/src/Components/Analyzers/test/Microsoft.AspNetCore.Components.Analyzers.Tests.csproj index a31c1a8f0e..45b379c65c 100644 --- a/src/Components/Analyzers/test/Microsoft.AspNetCore.Components.Analyzers.Tests.csproj +++ b/src/Components/Analyzers/test/Microsoft.AspNetCore.Components.Analyzers.Tests.csproj @@ -2,16 +2,24 @@ netcoreapp3.0 - - - - - + + + false + + + + + + + + + + diff --git a/src/Components/Analyzers/test/TestFiles/ComponentInternalUsageDiagnoticsAnalyzerTest/UsesRenderTreeFrameAsParameter.cs b/src/Components/Analyzers/test/TestFiles/ComponentInternalUsageDiagnoticsAnalyzerTest/UsesRenderTreeFrameAsParameter.cs new file mode 100644 index 0000000000..415030a011 --- /dev/null +++ b/src/Components/Analyzers/test/TestFiles/ComponentInternalUsageDiagnoticsAnalyzerTest/UsesRenderTreeFrameAsParameter.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Components.RenderTree; + +namespace Microsoft.AspNetCore.Components.Analyzers.Tests.TestFiles.ComponentInternalUsageDiagnoticsAnalyzerTest +{ + class UsesRenderTreeFrameAsParameter + { + private void Test(/*MM*/RenderTreeFrame frame) + { + } + } +} diff --git a/src/Components/Analyzers/test/TestFiles/ComponentInternalUsageDiagnoticsAnalyzerTest/UsesRenderTreeFrameTypeAsLocal.cs b/src/Components/Analyzers/test/TestFiles/ComponentInternalUsageDiagnoticsAnalyzerTest/UsesRenderTreeFrameTypeAsLocal.cs new file mode 100644 index 0000000000..bdd40c2df1 --- /dev/null +++ b/src/Components/Analyzers/test/TestFiles/ComponentInternalUsageDiagnoticsAnalyzerTest/UsesRenderTreeFrameTypeAsLocal.cs @@ -0,0 +1,15 @@ +using System; +using Microsoft.AspNetCore.Components.RenderTree; + +namespace Microsoft.AspNetCore.Components.Analyzers.Tests.TestFiles.ComponentInternalUsageDiagnoticsAnalyzerTest +{ + class UsesRenderTreeFrameTypeAsLocal + { + private void Test() + { + var test = RenderTreeFrameType./*MM*/Attribute; + GC.KeepAlive(test); + } + + } +} diff --git a/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.0.cs b/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.0.cs index d56360f9aa..a2feb9c39c 100644 --- a/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.0.cs +++ b/src/Components/Blazor/Blazor/ref/Microsoft.AspNetCore.Blazor.netstandard2.0.cs @@ -65,16 +65,10 @@ namespace Microsoft.AspNetCore.Blazor.Http } namespace Microsoft.AspNetCore.Blazor.Rendering { - public partial class WebAssemblyRenderer : Microsoft.AspNetCore.Components.Rendering.Renderer + public static partial class WebAssemblyEventDispatcher { - public WebAssemblyRenderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) : base (default(System.IServiceProvider), default(Microsoft.Extensions.Logging.ILoggerFactory)) { } - public override Microsoft.AspNetCore.Components.Dispatcher Dispatcher { get { throw null; } } - public System.Threading.Tasks.Task AddComponentAsync(System.Type componentType, string domElementSelector) { throw null; } - public System.Threading.Tasks.Task AddComponentAsync(string domElementSelector) where TComponent : Microsoft.AspNetCore.Components.IComponent { throw null; } - public override System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.Rendering.EventFieldInfo eventFieldInfo, System.EventArgs eventArgs) { throw null; } - protected override void Dispose(bool disposing) { } - protected override void HandleException(System.Exception exception) { } - protected override System.Threading.Tasks.Task UpdateDisplayAsync(in Microsoft.AspNetCore.Components.Rendering.RenderBatch batch) { throw null; } + [Microsoft.JSInterop.JSInvokableAttribute("DispatchEvent")] + public static System.Threading.Tasks.Task DispatchEvent(Microsoft.AspNetCore.Components.Web.WebEventDescriptor eventDescriptor, string eventArgsJson) { throw null; } } } namespace Microsoft.AspNetCore.Components.Builder diff --git a/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj b/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj index 1a0e49e112..c571f776f0 100644 --- a/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj +++ b/src/Components/Blazor/Blazor/src/Microsoft.AspNetCore.Blazor.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 @@ -11,4 +11,10 @@ + + + + + + diff --git a/src/Components/Blazor/Blazor/src/Rendering/RendererRegistry.cs b/src/Components/Blazor/Blazor/src/Rendering/RendererRegistry.cs new file mode 100644 index 0000000000..c0f1f98e29 --- /dev/null +++ b/src/Components/Blazor/Blazor/src/Rendering/RendererRegistry.cs @@ -0,0 +1,46 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; + +namespace Microsoft.AspNetCore.Blazor.Rendering +{ + internal static class RendererRegistry + { + // In case there are multiple concurrent Blazor renderers in the same .NET WebAssembly + // process, we track them by ID. This allows events to be dispatched to the correct one, + // as well as rooting them for GC purposes, since nothing would otherwise be referencing + // them even though we might still receive incoming events from JS. + + private static int _nextId; + private static Dictionary _renderers = new Dictionary(); + + internal static WebAssemblyRenderer Find(int rendererId) + { + return _renderers.ContainsKey(rendererId) + ? _renderers[rendererId] + : throw new ArgumentException($"There is no renderer with ID {rendererId}."); + } + + public static int Add(WebAssemblyRenderer renderer) + { + var id = _nextId++; + _renderers.Add(id, renderer); + return id; + } + + public static bool TryRemove(int rendererId) + { + if (_renderers.ContainsKey(rendererId)) + { + _renderers.Remove(rendererId); + return true; + } + else + { + return false; + } + } + } +} diff --git a/src/Components/Blazor/Blazor/src/Rendering/WebAssemblyEventDispatcher.cs b/src/Components/Blazor/Blazor/src/Rendering/WebAssemblyEventDispatcher.cs new file mode 100644 index 0000000000..d46500bae7 --- /dev/null +++ b/src/Components/Blazor/Blazor/src/Rendering/WebAssemblyEventDispatcher.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.AspNetCore.Components.Web; +using Microsoft.JSInterop; + +namespace Microsoft.AspNetCore.Blazor.Rendering +{ + /// + /// Dispatches events from JavaScript to a Blazor WebAssembly renderer. + /// Intended for internal use only. + /// + public static class WebAssemblyEventDispatcher + { + /// + /// For framework use only. + /// + [JSInvokable(nameof(DispatchEvent))] + public static Task DispatchEvent(WebEventDescriptor eventDescriptor, string eventArgsJson) + { + var webEvent = WebEventData.Parse(eventDescriptor, eventArgsJson); + var renderer = RendererRegistry.Find(eventDescriptor.BrowserRendererId); + return renderer.DispatchEventAsync( + webEvent.EventHandlerId, + webEvent.EventFieldInfo, + webEvent.EventArgs); + } + } +} diff --git a/src/Components/Blazor/Blazor/src/Rendering/WebAssemblyRenderer.cs b/src/Components/Blazor/Blazor/src/Rendering/WebAssemblyRenderer.cs index d4e867621e..5964637090 100644 --- a/src/Components/Blazor/Blazor/src/Rendering/WebAssemblyRenderer.cs +++ b/src/Components/Blazor/Blazor/src/Rendering/WebAssemblyRenderer.cs @@ -6,7 +6,6 @@ using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Blazor.Services; using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.Rendering; using Microsoft.Extensions.Logging; @@ -16,7 +15,7 @@ namespace Microsoft.AspNetCore.Blazor.Rendering /// Provides mechanisms for rendering instances in a /// web browser, dispatching events to them, and refreshing the UI as required. /// - public class WebAssemblyRenderer : Renderer + internal class WebAssemblyRenderer : Renderer { private readonly int _webAssemblyRendererId; @@ -31,10 +30,8 @@ namespace Microsoft.AspNetCore.Blazor.Rendering public WebAssemblyRenderer(IServiceProvider serviceProvider, ILoggerFactory loggerFactory) : base(serviceProvider, loggerFactory) { - // The browser renderer registers and unregisters itself with the static - // registry. This works well with the WebAssembly runtime, and is simple for the - // case where Blazor is running in process. - _webAssemblyRendererId = RendererRegistry.Current.Add(this); + // The WebAssembly renderer registers and unregisters itself with the static registry + _webAssemblyRendererId = RendererRegistry.Add(this); } public override Dispatcher Dispatcher => NullDispatcher.Instance; @@ -77,9 +74,9 @@ namespace Microsoft.AspNetCore.Blazor.Rendering WebAssemblyJSRuntime.Instance.Invoke( "Blazor._internal.attachRootComponentToElement", - _webAssemblyRendererId, domElementSelector, - componentId); + componentId, + _webAssemblyRendererId); return RenderRootComponentAsync(componentId); } @@ -88,7 +85,7 @@ namespace Microsoft.AspNetCore.Blazor.Rendering protected override void Dispose(bool disposing) { base.Dispose(disposing); - RendererRegistry.Current.TryRemove(_webAssemblyRendererId); + RendererRegistry.TryRemove(_webAssemblyRendererId); } /// diff --git a/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.csproj b/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.csproj index ab757d5c82..adfa71ef6b 100644 --- a/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.csproj +++ b/src/Components/Blazor/Build/src/Microsoft.AspNetCore.Blazor.Build.csproj @@ -26,7 +26,7 @@ - + diff --git a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets index 96a844817e..42ef903f15 100644 --- a/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets +++ b/src/Components/Blazor/Build/src/targets/Blazor.MonoRuntime.targets @@ -436,9 +436,15 @@ + + + + <_MonoLinkerDotNetPath>$(DOTNET_HOST_PATH) + <_MonoLinkerDotNetPath Condition="'$(_MonoLinkerDotNetPath)' == ''">dotnet + - + diff --git a/src/Components/Blazor/Build/test/ChildContentRazorIntegrationTest.cs b/src/Components/Blazor/Build/test/ChildContentRazorIntegrationTest.cs index 90090cb070..720c00fe9b 100644 --- a/src/Components/Blazor/Build/test/ChildContentRazorIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/ChildContentRazorIntegrationTest.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.Test.Helpers; using Microsoft.CodeAnalysis.CSharp; using Xunit; @@ -14,7 +13,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test { private readonly CSharpSyntaxTree RenderChildContentComponent = Parse(@" using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.RenderTree; +using Microsoft.AspNetCore.Components.Rendering; namespace Test { public class RenderChildContent : ComponentBase @@ -32,7 +31,7 @@ namespace Test private readonly CSharpSyntaxTree RenderChildContentStringComponent = Parse(@" using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.RenderTree; +using Microsoft.AspNetCore.Components.Rendering; namespace Test { public class RenderChildContentString : ComponentBase @@ -53,7 +52,7 @@ namespace Test private readonly CSharpSyntaxTree RenderMultipleChildContent = Parse(@" using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.RenderTree; +using Microsoft.AspNetCore.Components.Rendering; namespace Test { public class RenderMultipleChildContent : ComponentBase diff --git a/src/Components/Blazor/Build/test/ComponentRenderingRazorIntegrationTest.cs b/src/Components/Blazor/Build/test/ComponentRenderingRazorIntegrationTest.cs index 6c0a7fab96..6513224c05 100644 --- a/src/Components/Blazor/Build/test/ComponentRenderingRazorIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/ComponentRenderingRazorIntegrationTest.cs @@ -565,7 +565,7 @@ namespace Test // Arrange AdditionalSyntaxTrees.Add(Parse(@" using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.RenderTree; +using Microsoft.AspNetCore.Components.Rendering; namespace Test { diff --git a/src/Components/Blazor/Build/test/GenericComponentRazorIntegrationTest.cs b/src/Components/Blazor/Build/test/GenericComponentRazorIntegrationTest.cs index 45c178e4bb..299683b68f 100644 --- a/src/Components/Blazor/Build/test/GenericComponentRazorIntegrationTest.cs +++ b/src/Components/Blazor/Build/test/GenericComponentRazorIntegrationTest.cs @@ -5,7 +5,6 @@ using System; using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.RenderTree; using Microsoft.AspNetCore.Components.Test.Helpers; using Microsoft.CodeAnalysis.CSharp; using Xunit; @@ -19,7 +18,7 @@ namespace Microsoft.AspNetCore.Blazor.Build.Test using System; using System.Collections.Generic; using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.RenderTree; +using Microsoft.AspNetCore.Components.Rendering; namespace Test { public class GenericContext : ComponentBase @@ -57,7 +56,7 @@ namespace Test private readonly CSharpSyntaxTree MultipleGenericParameterComponent = Parse(@" using Microsoft.AspNetCore.Components; -using Microsoft.AspNetCore.Components.RenderTree; +using Microsoft.AspNetCore.Components.Rendering; namespace Test { public class MultipleGenericParameter : ComponentBase diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/App.razor b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/App.razor index c5ee6a53e2..1c360b7121 100644 --- a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/App.razor +++ b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/App.razor @@ -1,5 +1,10 @@ - + + + + - Sorry, there's nothing at this address. + + Sorry, there's nothing at this address. + diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Pages/_Imports.razor b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Pages/_Imports.razor deleted file mode 100644 index 0f24edaf1d..0000000000 --- a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Pages/_Imports.razor +++ /dev/null @@ -1 +0,0 @@ -@layout MainLayout diff --git a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor index 5baad704a9..d392ed3eeb 100644 --- a/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor +++ b/src/Components/Blazor/Templates/src/content/BlazorWasm-CSharp/Client/Shared/SurveyPrompt.razor @@ -4,7 +4,7 @@ Please take our - brief survey + brief survey and tell us what you think. diff --git a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/App.razor b/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/App.razor index 7f4cf93fbb..fe885300e7 100644 --- a/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/App.razor +++ b/src/Components/Blazor/testassets/Microsoft.AspNetCore.Blazor.E2EPerformance/App.razor @@ -1 +1,8 @@ - + + + + + + Sorry, there's nothing here. + + diff --git a/src/Components/Blazor/testassets/MonoSanityClient/MonoSanityClient.csproj b/src/Components/Blazor/testassets/MonoSanityClient/MonoSanityClient.csproj index e40ea493bd..b186c39194 100644 --- a/src/Components/Blazor/testassets/MonoSanityClient/MonoSanityClient.csproj +++ b/src/Components/Blazor/testassets/MonoSanityClient/MonoSanityClient.csproj @@ -11,7 +11,4 @@ true - - - diff --git a/src/Components/Blazor/testassets/StandaloneApp/App.razor b/src/Components/Blazor/testassets/StandaloneApp/App.razor index 4b8a0ffa42..fe6830bb01 100644 --- a/src/Components/Blazor/testassets/StandaloneApp/App.razor +++ b/src/Components/Blazor/testassets/StandaloneApp/App.razor @@ -1,5 +1,11 @@ - - + + + + + + + Not found + Sorry, there's nothing at this address. + + + diff --git a/src/Components/Blazor/testassets/StandaloneApp/Pages/_Imports.razor b/src/Components/Blazor/testassets/StandaloneApp/Pages/_Imports.razor deleted file mode 100644 index 5e11c2a20c..0000000000 --- a/src/Components/Blazor/testassets/StandaloneApp/Pages/_Imports.razor +++ /dev/null @@ -1 +0,0 @@ -@layout MainLayout diff --git a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs b/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs index 4f317be0ff..e3d29e6a52 100644 --- a/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs +++ b/src/Components/Components/ref/Microsoft.AspNetCore.Components.netstandard2.0.cs @@ -16,6 +16,15 @@ namespace Microsoft.AspNetCore.Components public abstract System.Threading.Tasks.Task GetAuthenticationStateAsync(); protected void NotifyAuthenticationStateChanged(System.Threading.Tasks.Task task) { } } + public sealed partial class AuthorizeRouteView : Microsoft.AspNetCore.Components.RouteView + { + public AuthorizeRouteView() { } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public Microsoft.AspNetCore.Components.RenderFragment Authorizing { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public Microsoft.AspNetCore.Components.RenderFragment NotAuthorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + protected override void Render(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } + } public partial class AuthorizeView : Microsoft.AspNetCore.Components.AuthorizeViewCore { public AuthorizeView() { } @@ -38,7 +47,7 @@ namespace Microsoft.AspNetCore.Components public Microsoft.AspNetCore.Components.RenderFragment NotAuthorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } [Microsoft.AspNetCore.Components.ParameterAttribute] public object Resource { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } + protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } protected abstract Microsoft.AspNetCore.Authorization.IAuthorizeData[] GetAuthorizeData(); [System.Diagnostics.DebuggerStepThroughAttribute] protected override System.Threading.Tasks.Task OnParametersSetAsync() { throw null; } @@ -95,7 +104,7 @@ namespace Microsoft.AspNetCore.Components public CascadingAuthenticationState() { } [Microsoft.AspNetCore.Components.ParameterAttribute] public Microsoft.AspNetCore.Components.RenderFragment ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - protected override void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } + protected override void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } protected override void OnInitialized() { } void System.IDisposable.Dispose() { } } @@ -105,7 +114,7 @@ namespace Microsoft.AspNetCore.Components public CascadingParameterAttribute() { } public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } } - public partial class CascadingValue : Microsoft.AspNetCore.Components.IComponent + public partial class CascadingValue : Microsoft.AspNetCore.Components.IComponent { public CascadingValue() { } [Microsoft.AspNetCore.Components.ParameterAttribute] @@ -115,7 +124,7 @@ namespace Microsoft.AspNetCore.Components [Microsoft.AspNetCore.Components.ParameterAttribute] public string Name { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } [Microsoft.AspNetCore.Components.ParameterAttribute] - public T Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public TValue Value { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } } @@ -127,7 +136,7 @@ namespace Microsoft.AspNetCore.Components public abstract partial class ComponentBase : Microsoft.AspNetCore.Components.IComponent, Microsoft.AspNetCore.Components.IHandleAfterRender, Microsoft.AspNetCore.Components.IHandleEvent { public ComponentBase() { } - protected virtual void BuildRenderTree(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder) { } + protected virtual void BuildRenderTree(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } protected System.Threading.Tasks.Task InvokeAsync(System.Action workItem) { throw null; } protected System.Threading.Tasks.Task InvokeAsync(System.Func workItem) { throw null; } void Microsoft.AspNetCore.Components.IComponent.Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } @@ -179,17 +188,17 @@ namespace Microsoft.AspNetCore.Components public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Func callback) { throw null; } public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Func callback) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public Microsoft.AspNetCore.Components.EventCallback CreateInferred(object receiver, System.Action callback, T value) { throw null; } + public Microsoft.AspNetCore.Components.EventCallback CreateInferred(object receiver, System.Action callback, TValue value) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public Microsoft.AspNetCore.Components.EventCallback CreateInferred(object receiver, System.Func callback, T value) { throw null; } + public Microsoft.AspNetCore.Components.EventCallback CreateInferred(object receiver, System.Func callback, TValue value) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, Microsoft.AspNetCore.Components.EventCallback callback) { throw null; } + public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, Microsoft.AspNetCore.Components.EventCallback callback) { throw null; } [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, Microsoft.AspNetCore.Components.EventCallback callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Action callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Action callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Func callback) { throw null; } - public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Func callback) { throw null; } + public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, Microsoft.AspNetCore.Components.EventCallback callback) { throw null; } + public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Action callback) { throw null; } + public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Action callback) { throw null; } + public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Func callback) { throw null; } + public Microsoft.AspNetCore.Components.EventCallback Create(object receiver, System.Func callback) { throw null; } } public static partial class EventCallbackFactoryBinderExtensions { @@ -232,13 +241,13 @@ namespace Microsoft.AspNetCore.Components public System.Threading.Tasks.Task InvokeAsync(object arg) { throw null; } } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] - public readonly partial struct EventCallback + public readonly partial struct EventCallback { private readonly object _dummy; - public static readonly Microsoft.AspNetCore.Components.EventCallback Empty; + public static readonly Microsoft.AspNetCore.Components.EventCallback Empty; public EventCallback(Microsoft.AspNetCore.Components.IHandleEvent receiver, System.MulticastDelegate @delegate) { throw null; } public bool HasDelegate { get { throw null; } } - public System.Threading.Tasks.Task InvokeAsync(T arg) { throw null; } + public System.Threading.Tasks.Task InvokeAsync(TValue arg) { throw null; } } public partial interface IComponent { @@ -278,6 +287,16 @@ namespace Microsoft.AspNetCore.Components [Microsoft.AspNetCore.Components.ParameterAttribute] public Microsoft.AspNetCore.Components.RenderFragment Body { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } } + public partial class LayoutView : Microsoft.AspNetCore.Components.IComponent + { + public LayoutView() { } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public Microsoft.AspNetCore.Components.RenderFragment ChildContent { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public System.Type Layout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } + public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } + } public sealed partial class LocationChangeException : System.Exception { public LocationChangeException(string message, System.Exception innerException) { } @@ -323,20 +342,6 @@ namespace Microsoft.AspNetCore.Components protected OwningComponentBase() { } protected TService Service { get { throw null; } } } - public partial class PageDisplay : Microsoft.AspNetCore.Components.IComponent - { - public PageDisplay() { } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment Authorizing { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment NotAuthorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public System.Type Page { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public System.Collections.Generic.IDictionary PageParameters { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } - public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } - } [System.AttributeUsageAttribute(System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)] public sealed partial class ParameterAttribute : System.Attribute { @@ -360,11 +365,11 @@ namespace Microsoft.AspNetCore.Components public static Microsoft.AspNetCore.Components.ParameterView Empty { get { throw null; } } public static Microsoft.AspNetCore.Components.ParameterView FromDictionary(System.Collections.Generic.IDictionary parameters) { throw null; } public Microsoft.AspNetCore.Components.ParameterView.Enumerator GetEnumerator() { throw null; } - public T GetValueOrDefault(string parameterName) { throw null; } - public T GetValueOrDefault(string parameterName, T defaultValue) { throw null; } + public TValue GetValueOrDefault(string parameterName) { throw null; } + public TValue GetValueOrDefault(string parameterName, TValue defaultValue) { throw null; } public void SetParameterProperties(object target) { } public System.Collections.Generic.IReadOnlyDictionary ToDictionary() { throw null; } - public bool TryGetValue(string parameterName, out T result) { throw null; } + public bool TryGetValue(string parameterName, out TValue result) { throw null; } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public partial struct Enumerator { @@ -374,8 +379,8 @@ namespace Microsoft.AspNetCore.Components public bool MoveNext() { throw null; } } } - public delegate void RenderFragment(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder); - public delegate Microsoft.AspNetCore.Components.RenderFragment RenderFragment(T value); + public delegate void RenderFragment(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder); + public delegate Microsoft.AspNetCore.Components.RenderFragment RenderFragment(TValue value); [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public readonly partial struct RenderHandle { @@ -391,6 +396,23 @@ namespace Microsoft.AspNetCore.Components public RouteAttribute(string template) { } public string Template { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } } + public sealed partial class RouteData + { + public RouteData(System.Type pageType, System.Collections.Generic.IReadOnlyDictionary routeValues) { } + public System.Type PageType { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + public System.Collections.Generic.IReadOnlyDictionary RouteValues { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } + } + public partial class RouteView : Microsoft.AspNetCore.Components.IComponent + { + public RouteView() { } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public System.Type DefaultLayout { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + [Microsoft.AspNetCore.Components.ParameterAttribute] + public Microsoft.AspNetCore.Components.RouteData RouteData { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } + protected virtual void Render(Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder builder) { } + public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } + } } namespace Microsoft.AspNetCore.Components.CompilerServices { @@ -444,7 +466,7 @@ namespace Microsoft.AspNetCore.Components.Forms public FieldIdentifier(object model, string fieldName) { throw null; } public string FieldName { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } public object Model { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } } - public static Microsoft.AspNetCore.Components.Forms.FieldIdentifier Create(System.Linq.Expressions.Expression> accessor) { throw null; } + public static Microsoft.AspNetCore.Components.Forms.FieldIdentifier Create(System.Linq.Expressions.Expression> accessor) { throw null; } public bool Equals(Microsoft.AspNetCore.Components.Forms.FieldIdentifier otherIdentifier) { throw null; } public override bool Equals(object obj) { throw null; } public override int GetHashCode() { throw null; } @@ -513,18 +535,50 @@ namespace Microsoft.AspNetCore.Components.Rendering public Renderer(System.IServiceProvider serviceProvider, Microsoft.Extensions.Logging.ILoggerFactory loggerFactory) { } public abstract Microsoft.AspNetCore.Components.Dispatcher Dispatcher { get; } public event System.UnhandledExceptionEventHandler UnhandledSynchronizationException { add { } remove { } } - protected internal virtual void AddToRenderQueue(int componentId, Microsoft.AspNetCore.Components.RenderFragment renderFragment) { } protected internal int AssignRootComponentId(Microsoft.AspNetCore.Components.IComponent component) { throw null; } public virtual System.Threading.Tasks.Task DispatchEventAsync(ulong eventHandlerId, Microsoft.AspNetCore.Components.Rendering.EventFieldInfo fieldInfo, System.EventArgs eventArgs) { throw null; } public void Dispose() { } protected virtual void Dispose(bool disposing) { } protected abstract void HandleException(System.Exception exception); protected Microsoft.AspNetCore.Components.IComponent InstantiateComponent(System.Type componentType) { throw null; } + protected virtual void ProcessPendingRender() { } protected System.Threading.Tasks.Task RenderRootComponentAsync(int componentId) { throw null; } [System.Diagnostics.DebuggerStepThroughAttribute] protected System.Threading.Tasks.Task RenderRootComponentAsync(int componentId, Microsoft.AspNetCore.Components.ParameterView initialParameters) { throw null; } protected abstract System.Threading.Tasks.Task UpdateDisplayAsync(in Microsoft.AspNetCore.Components.Rendering.RenderBatch renderBatch); } + public sealed partial class RenderTreeBuilder : System.IDisposable + { + public RenderTreeBuilder() { } + public void AddAttribute(int sequence, in Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame frame) { } + public void AddAttribute(int sequence, string name, Microsoft.AspNetCore.Components.EventCallback value) { } + public void AddAttribute(int sequence, string name, bool value) { } + public void AddAttribute(int sequence, string name, System.MulticastDelegate value) { } + public void AddAttribute(int sequence, string name, object value) { } + public void AddAttribute(int sequence, string name, string value) { } + public void AddAttribute(int sequence, string name, Microsoft.AspNetCore.Components.EventCallback value) { } + public void AddComponentReferenceCapture(int sequence, System.Action componentReferenceCaptureAction) { } + public void AddContent(int sequence, Microsoft.AspNetCore.Components.MarkupString markupContent) { } + public void AddContent(int sequence, Microsoft.AspNetCore.Components.RenderFragment fragment) { } + public void AddContent(int sequence, object textContent) { } + public void AddContent(int sequence, string textContent) { } + public void AddContent(int sequence, Microsoft.AspNetCore.Components.RenderFragment fragment, TValue value) { } + public void AddElementReferenceCapture(int sequence, System.Action elementReferenceCaptureAction) { } + public void AddMarkupContent(int sequence, string markupContent) { } + public void AddMultipleAttributes(int sequence, System.Collections.Generic.IEnumerable> attributes) { } + public void Clear() { } + public void CloseComponent() { } + public void CloseElement() { } + public void CloseRegion() { } + public Microsoft.AspNetCore.Components.RenderTree.ArrayRange GetFrames() { throw null; } + public void OpenComponent(int sequence, System.Type componentType) { } + public void OpenComponent(int sequence) where TComponent : Microsoft.AspNetCore.Components.IComponent { } + public void OpenElement(int sequence, string elementName) { } + public void OpenRegion(int sequence) { } + public void SetKey(object value) { } + public void SetUpdatesAttributeName(string updatesAttributeName) { } + void System.IDisposable.Dispose() { } + } } namespace Microsoft.AspNetCore.Components.RenderTree { @@ -548,38 +602,6 @@ namespace Microsoft.AspNetCore.Components.RenderTree public ArrayRange(T[] array, int count) { throw null; } public Microsoft.AspNetCore.Components.RenderTree.ArrayRange Clone() { throw null; } } - public sealed partial class RenderTreeBuilder : System.IDisposable - { - public RenderTreeBuilder() { } - public void AddAttribute(int sequence, in Microsoft.AspNetCore.Components.RenderTree.RenderTreeFrame frame) { } - public void AddAttribute(int sequence, string name, Microsoft.AspNetCore.Components.EventCallback value) { } - public void AddAttribute(int sequence, string name, bool value) { } - public void AddAttribute(int sequence, string name, System.MulticastDelegate value) { } - public void AddAttribute(int sequence, string name, object value) { } - public void AddAttribute(int sequence, string name, string value) { } - public void AddAttribute(int sequence, string name, Microsoft.AspNetCore.Components.EventCallback value) { } - public void AddComponentReferenceCapture(int sequence, System.Action componentReferenceCaptureAction) { } - public void AddContent(int sequence, Microsoft.AspNetCore.Components.MarkupString markupContent) { } - public void AddContent(int sequence, Microsoft.AspNetCore.Components.RenderFragment fragment) { } - public void AddContent(int sequence, object textContent) { } - public void AddContent(int sequence, string textContent) { } - public void AddContent(int sequence, Microsoft.AspNetCore.Components.RenderFragment fragment, T value) { } - public void AddElementReferenceCapture(int sequence, System.Action elementReferenceCaptureAction) { } - public void AddMarkupContent(int sequence, string markupContent) { } - public void AddMultipleAttributes(int sequence, System.Collections.Generic.IEnumerable> attributes) { } - public void Clear() { } - public void CloseComponent() { } - public void CloseElement() { } - public void CloseRegion() { } - public Microsoft.AspNetCore.Components.RenderTree.ArrayRange GetFrames() { throw null; } - public void OpenComponent(int sequence, System.Type componentType) { } - public void OpenComponent(int sequence) where TComponent : Microsoft.AspNetCore.Components.IComponent { } - public void OpenElement(int sequence, string elementName) { } - public void OpenRegion(int sequence) { } - public void SetKey(object value) { } - public void SetUpdatesAttributeName(string updatesAttributeName) { } - void System.IDisposable.Dispose() { } - } [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] public readonly partial struct RenderTreeDiff { @@ -648,15 +670,12 @@ namespace Microsoft.AspNetCore.Components.Routing [Microsoft.AspNetCore.Components.ParameterAttribute] public System.Reflection.Assembly AppAssembly { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment Authorizing { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } - [Microsoft.AspNetCore.Components.ParameterAttribute] - public Microsoft.AspNetCore.Components.RenderFragment NotAuthorized { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } + public Microsoft.AspNetCore.Components.RenderFragment Found { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } [Microsoft.AspNetCore.Components.ParameterAttribute] public Microsoft.AspNetCore.Components.RenderFragment NotFound { [System.Runtime.CompilerServices.CompilerGeneratedAttribute]get { throw null; } [System.Runtime.CompilerServices.CompilerGeneratedAttribute]set { } } public void Attach(Microsoft.AspNetCore.Components.RenderHandle renderHandle) { } public void Dispose() { } System.Threading.Tasks.Task Microsoft.AspNetCore.Components.IHandleAfterRender.OnAfterRenderAsync() { throw null; } - protected virtual void Render(Microsoft.AspNetCore.Components.RenderTree.RenderTreeBuilder builder, System.Type handler, System.Collections.Generic.IDictionary parameters) { } public System.Threading.Tasks.Task SetParametersAsync(Microsoft.AspNetCore.Components.ParameterView parameters) { throw null; } } } diff --git a/src/Components/Components/src/Auth/AuthorizeRouteView.cs b/src/Components/Components/src/Auth/AuthorizeRouteView.cs new file mode 100644 index 0000000000..b0d01ab093 --- /dev/null +++ b/src/Components/Components/src/Auth/AuthorizeRouteView.cs @@ -0,0 +1,118 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Components.Auth; +using Microsoft.AspNetCore.Components.Rendering; + +namespace Microsoft.AspNetCore.Components +{ + /// + /// Combines the behaviors of and , + /// so that it displays the page matching the specified route but only if the user + /// is authorized to see it. + /// + /// Additionally, this component supplies a cascading parameter of type , + /// which makes the user's current authentication state available to descendants. + /// + public sealed class AuthorizeRouteView : RouteView + { + // We expect applications to supply their own authorizing/not-authorized content, but + // it's better to have defaults than to make the parameters mandatory because in some + // cases they will never be used (e.g., "authorizing" in out-of-box server-side Blazor) + private static readonly RenderFragment _defaultNotAuthorizedContent + = state => builder => builder.AddContent(0, "Not authorized"); + private static readonly RenderFragment _defaultAuthorizingContent + = builder => builder.AddContent(0, "Authorizing..."); + + private readonly RenderFragment _renderAuthorizeRouteViewCoreDelegate; + private readonly RenderFragment _renderAuthorizedDelegate; + private readonly RenderFragment _renderNotAuthorizedDelegate; + private readonly RenderFragment _renderAuthorizingDelegate; + + public AuthorizeRouteView() + { + // Cache the rendering delegates so that we only construct new closure instances + // when they are actually used (e.g., we never prepare a RenderFragment bound to + // the NotAuthorized content except when you are displaying that particular state) + RenderFragment renderBaseRouteViewDelegate = builder => base.Render(builder); + _renderAuthorizedDelegate = authenticateState => renderBaseRouteViewDelegate; + _renderNotAuthorizedDelegate = authenticationState => builder => RenderNotAuthorizedInDefaultLayout(builder, authenticationState); + _renderAuthorizingDelegate = RenderAuthorizingInDefaultLayout; + _renderAuthorizeRouteViewCoreDelegate = RenderAuthorizeRouteViewCore; + } + + /// + /// The content that will be displayed if the user is not authorized. + /// + [Parameter] + public RenderFragment NotAuthorized { get; set; } + + /// + /// The content that will be displayed while asynchronous authorization is in progress. + /// + [Parameter] + public RenderFragment Authorizing { get; set; } + + [CascadingParameter] + private Task ExistingCascadedAuthenticationState { get; set; } + + /// + protected override void Render(RenderTreeBuilder builder) + { + if (ExistingCascadedAuthenticationState != null) + { + // If this component is already wrapped in a (or another + // compatible provider), then don't interfere with the cascaded authentication state. + _renderAuthorizeRouteViewCoreDelegate(builder); + } + else + { + // Otherwise, implicitly wrap the output in a + builder.OpenComponent(0); + builder.AddAttribute(1, nameof(CascadingAuthenticationState.ChildContent), _renderAuthorizeRouteViewCoreDelegate); + builder.CloseComponent(); + } + } + + private void RenderAuthorizeRouteViewCore(RenderTreeBuilder builder) + { + builder.OpenComponent(0); + builder.AddAttribute(1, nameof(AuthorizeRouteViewCore.RouteData), RouteData); + builder.AddAttribute(2, nameof(AuthorizeRouteViewCore.Authorized), _renderAuthorizedDelegate); + builder.AddAttribute(3, nameof(AuthorizeRouteViewCore.Authorizing), _renderAuthorizingDelegate); + builder.AddAttribute(4, nameof(AuthorizeRouteViewCore.NotAuthorized), _renderNotAuthorizedDelegate); + builder.CloseComponent(); + } + + private void RenderContentInDefaultLayout(RenderTreeBuilder builder, RenderFragment content) + { + builder.OpenComponent(0); + builder.AddAttribute(1, nameof(LayoutView.Layout), DefaultLayout); + builder.AddAttribute(2, nameof(LayoutView.ChildContent), content); + builder.CloseComponent(); + } + + private void RenderNotAuthorizedInDefaultLayout(RenderTreeBuilder builder, AuthenticationState authenticationState) + { + var content = NotAuthorized ?? _defaultNotAuthorizedContent; + RenderContentInDefaultLayout(builder, content(authenticationState)); + } + + private void RenderAuthorizingInDefaultLayout(RenderTreeBuilder builder) + { + var content = Authorizing ?? _defaultAuthorizingContent; + RenderContentInDefaultLayout(builder, content); + } + + private class AuthorizeRouteViewCore : AuthorizeViewCore + { + [Parameter] + public RouteData RouteData { get; set; } + + protected override IAuthorizeData[] GetAuthorizeData() + => AttributeAuthorizeDataCache.GetAuthorizeDataForType(RouteData.PageType); + } + } +} diff --git a/src/Components/Components/src/Auth/AuthorizeViewCore.cs b/src/Components/Components/src/Auth/AuthorizeViewCore.cs index 8c60078184..cdbce6e8d2 100644 --- a/src/Components/Components/src/Auth/AuthorizeViewCore.cs +++ b/src/Components/Components/src/Auth/AuthorizeViewCore.cs @@ -5,7 +5,7 @@ using System; using System.Security.Claims; using System.Threading.Tasks; using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Components.RenderTree; +using Microsoft.AspNetCore.Components.Rendering; namespace Microsoft.AspNetCore.Components { @@ -52,6 +52,8 @@ namespace Microsoft.AspNetCore.Components /// protected override void BuildRenderTree(RenderTreeBuilder builder) { + // We're using the same sequence number for each of the content items here + // so that we can update existing instances if they are the same shape if (currentAuthenticationState == null) { builder.AddContent(0, Authorizing); @@ -59,11 +61,11 @@ namespace Microsoft.AspNetCore.Components else if (isAuthorized) { var authorized = Authorized ?? ChildContent; - builder.AddContent(1, authorized?.Invoke(currentAuthenticationState)); + builder.AddContent(0, authorized?.Invoke(currentAuthenticationState)); } else { - builder.AddContent(2, NotAuthorized?.Invoke(currentAuthenticationState)); + builder.AddContent(0, NotAuthorized?.Invoke(currentAuthenticationState)); } } @@ -102,6 +104,12 @@ namespace Microsoft.AspNetCore.Components private async Task IsAuthorizedAsync(ClaimsPrincipal user) { var authorizeData = GetAuthorizeData(); + if (authorizeData == null) + { + // No authorization applies, so no need to consult the authorization service + return true; + } + EnsureNoAuthenticationSchemeSpecified(authorizeData); var policy = await AuthorizationPolicy.CombineAsync( diff --git a/src/Components/Components/src/Auth/CascadingAuthenticationState.razor b/src/Components/Components/src/Auth/CascadingAuthenticationState.razor index 4f2e2bd630..695ebd1972 100644 --- a/src/Components/Components/src/Auth/CascadingAuthenticationState.razor +++ b/src/Components/Components/src/Auth/CascadingAuthenticationState.razor @@ -2,7 +2,7 @@ @implements IDisposable @inject AuthenticationStateProvider AuthenticationStateProvider - + @code { private Task _currentAuthenticationStateTask; diff --git a/src/Components/Components/src/CascadingValue.cs b/src/Components/Components/src/CascadingValue.cs index 1a03c2557e..564ca99def 100644 --- a/src/Components/Components/src/CascadingValue.cs +++ b/src/Components/Components/src/CascadingValue.cs @@ -5,14 +5,13 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.AspNetCore.Components.Rendering; -using Microsoft.AspNetCore.Components.RenderTree; namespace Microsoft.AspNetCore.Components { /// /// A component that provides a cascading value to all descendant components. /// - public class CascadingValue : ICascadingValueComponent, IComponent + public class CascadingValue : ICascadingValueComponent, IComponent { private RenderHandle _renderHandle; private HashSet _subscribers; // Lazily instantiated @@ -26,7 +25,7 @@ namespace Microsoft.AspNetCore.Components /// /// The value to be provided. /// - [Parameter] public T Value { get; set; } + [Parameter] public TValue Value { get; set; } /// /// Optionally gives a name to the provided value. Descendant components @@ -74,7 +73,7 @@ namespace Microsoft.AspNetCore.Components { if (parameter.Name.Equals(nameof(Value), StringComparison.OrdinalIgnoreCase)) { - Value = (T)parameter.Value; + Value = (TValue)parameter.Value; hasSuppliedValue = true; } else if (parameter.Name.Equals(nameof(ChildContent), StringComparison.OrdinalIgnoreCase)) @@ -86,7 +85,7 @@ namespace Microsoft.AspNetCore.Components Name = (string)parameter.Value; if (string.IsNullOrEmpty(Name)) { - throw new ArgumentException($"The parameter '{nameof(Name)}' for component '{nameof(CascadingValue)}' does not allow null or empty values."); + throw new ArgumentException($"The parameter '{nameof(Name)}' for component '{nameof(CascadingValue)}' does not allow null or empty values."); } } else if (parameter.Name.Equals(nameof(IsFixed), StringComparison.OrdinalIgnoreCase)) @@ -95,7 +94,7 @@ namespace Microsoft.AspNetCore.Components } else { - throw new ArgumentException($"The component '{nameof(CascadingValue)}' does not accept a parameter with the name '{parameter.Name}'."); + throw new ArgumentException($"The component '{nameof(CascadingValue)}' does not accept a parameter with the name '{parameter.Name}'."); } } @@ -136,7 +135,7 @@ namespace Microsoft.AspNetCore.Components bool ICascadingValueComponent.CanSupplyValue(Type requestedType, string requestedName) { - if (!requestedType.IsAssignableFrom(typeof(T))) + if (!requestedType.IsAssignableFrom(typeof(TValue))) { return false; } diff --git a/src/Components/Components/src/ComponentBase.cs b/src/Components/Components/src/ComponentBase.cs index baa91fd458..018c016975 100644 --- a/src/Components/Components/src/ComponentBase.cs +++ b/src/Components/Components/src/ComponentBase.cs @@ -3,7 +3,7 @@ using System; using System.Threading.Tasks; -using Microsoft.AspNetCore.Components.RenderTree; +using Microsoft.AspNetCore.Components.Rendering; namespace Microsoft.AspNetCore.Components { @@ -171,10 +171,25 @@ namespace Microsoft.AspNetCore.Components _renderHandle = renderHandle; } + /// - /// Method invoked to apply initial or updated parameters to the component. + /// Sets parameters supplied by the component's parent in the render tree. /// - /// The parameters to apply. + /// The parameters. + /// A that completes when the component has finished updating and rendering itself. + /// + /// + /// The method should be passed the entire set of parameter values each + /// time is called. It not required that the caller supply a parameter + /// value for all parameters that are logically understood by the component. + /// + /// + /// The default implementation of will set the value of each property + /// decorated with or that has + /// a corresponding value in the . Parameters that do not have a corresponding value + /// will be unchanged. + /// + /// public virtual Task SetParametersAsync(ParameterView parameters) { parameters.SetParameterProperties(this); diff --git a/src/Components/Components/src/ComponentFactory.cs b/src/Components/Components/src/ComponentFactory.cs index aebf96bc06..bf5de30d2a 100644 --- a/src/Components/Components/src/ComponentFactory.cs +++ b/src/Components/Components/src/ComponentFactory.cs @@ -61,7 +61,7 @@ namespace Microsoft.AspNetCore.Components ( propertyName: property.Name, propertyType: property.PropertyType, - setter: MemberAssignment.CreatePropertySetter(type, property) + setter: MemberAssignment.CreatePropertySetter(type, property, cascading: false) )).ToArray(); return Initialize; diff --git a/src/Components/Components/src/EventCallback.cs b/src/Components/Components/src/EventCallback.cs index 0d37124c64..3ba05ceaba 100644 --- a/src/Components/Components/src/EventCallback.cs +++ b/src/Components/Components/src/EventCallback.cs @@ -25,7 +25,7 @@ namespace Microsoft.AspNetCore.Components internal readonly IHandleEvent Receiver; /// - /// Creates the new . + /// Creates the new . /// /// The event receiver. /// The delegate to bind. @@ -66,73 +66,4 @@ namespace Microsoft.AspNetCore.Components return RequiresExplicitReceiver ? (object)this : Delegate; } } - - /// - /// A bound event handler delegate. - /// - public readonly struct EventCallback : IEventCallback - { - /// - /// Gets an empty . - /// - public static readonly EventCallback Empty = new EventCallback(null, (Action)(() => { })); - - internal readonly MulticastDelegate Delegate; - internal readonly IHandleEvent Receiver; - - /// - /// Creates the new . - /// - /// The event receiver. - /// The delegate to bind. - public EventCallback(IHandleEvent receiver, MulticastDelegate @delegate) - { - Receiver = receiver; - Delegate = @delegate; - } - - /// - /// Gets a value that indicates whether the delegate associated with this event dispatcher is non-null. - /// - public bool HasDelegate => Delegate != null; - - // This is a hint to the runtime that Receiver is a different object than what - // Delegate.Target points to. This allows us to avoid boxing the command object - // when building the render tree. See logic where this is used. - internal bool RequiresExplicitReceiver => Receiver != null && !object.ReferenceEquals(Receiver, Delegate?.Target); - - /// - /// Invokes the delegate associated with this binding and dispatches an event notification to the - /// appropriate component. - /// - /// The argument. - /// A which completes asynchronously once event processing has completed. - public Task InvokeAsync(T arg) - { - if (Receiver == null) - { - return EventCallbackWorkItem.InvokeAsync(Delegate, arg); - } - - return Receiver.HandleEventAsync(new EventCallbackWorkItem(Delegate), arg); - } - - internal EventCallback AsUntyped() - { - return new EventCallback(Receiver ?? Delegate?.Target as IHandleEvent, Delegate); - } - - object IEventCallback.UnpackForRenderTree() - { - return RequiresExplicitReceiver ? (object)AsUntyped() : Delegate; - } - } - - // Used to understand boxed generic EventCallbacks - internal interface IEventCallback - { - bool HasDelegate { get; } - - object UnpackForRenderTree(); - } } diff --git a/src/Components/Components/src/EventCallbackFactory.cs b/src/Components/Components/src/EventCallbackFactory.cs index a920d2277d..1b53376b85 100644 --- a/src/Components/Components/src/EventCallbackFactory.cs +++ b/src/Components/Components/src/EventCallbackFactory.cs @@ -105,14 +105,14 @@ namespace Microsoft.AspNetCore.Components /// /// [EditorBrowsable(EditorBrowsableState.Never)] - public EventCallback Create(object receiver, EventCallback callback) + public EventCallback Create(object receiver, EventCallback callback) { if (receiver == null) { throw new ArgumentNullException(nameof(receiver)); } - return new EventCallback(callback.Receiver, callback.Delegate); + return new EventCallback(callback.Receiver, callback.Delegate); } /// @@ -122,7 +122,7 @@ namespace Microsoft.AspNetCore.Components /// /// [EditorBrowsable(EditorBrowsableState.Never)] - public EventCallback Create(object receiver, EventCallback callback) + public EventCallback Create(object receiver, EventCallback callback) { if (receiver == null) { @@ -139,14 +139,14 @@ namespace Microsoft.AspNetCore.Components /// The event receiver. /// The event callback. /// The . - public EventCallback Create(object receiver, Action callback) + public EventCallback Create(object receiver, Action callback) { if (receiver == null) { throw new ArgumentNullException(nameof(receiver)); } - return CreateCore(receiver, callback); + return CreateCore(receiver, callback); } /// @@ -156,14 +156,14 @@ namespace Microsoft.AspNetCore.Components /// The event receiver. /// The event callback. /// The . - public EventCallback Create(object receiver, Action callback) + public EventCallback Create(object receiver, Action callback) { if (receiver == null) { throw new ArgumentNullException(nameof(receiver)); } - return CreateCore(receiver, callback); + return CreateCore(receiver, callback); } /// @@ -173,14 +173,14 @@ namespace Microsoft.AspNetCore.Components /// The event receiver. /// The event callback. /// The . - public EventCallback Create(object receiver, Func callback) + public EventCallback Create(object receiver, Func callback) { if (receiver == null) { throw new ArgumentNullException(nameof(receiver)); } - return CreateCore(receiver, callback); + return CreateCore(receiver, callback); } /// @@ -190,14 +190,14 @@ namespace Microsoft.AspNetCore.Components /// The event receiver. /// The event callback. /// The
Sorry, there's nothing at this address.