├── .editorconfig ├── .gitignore ├── CODE-OF-CONDUCT.md ├── Directory.Build.props ├── Directory.Build.targets ├── LICENSE.txt ├── NuGet.config ├── README.md ├── SECURITY.md ├── THIRD-PARTY-NOTICES.txt ├── build.sh ├── dotnet.sh ├── eng ├── Build.props ├── BuildTask.targets ├── Publishing.props ├── Version.Details.xml ├── Versions.props ├── azure-pipelines.yml └── common │ ├── BuildConfiguration │ └── build-configuration.json │ ├── CIBuild.cmd │ ├── PSScriptAnalyzerSettings.psd1 │ ├── README.md │ ├── SetupNugetSources.ps1 │ ├── SetupNugetSources.sh │ ├── build.cmd │ ├── build.ps1 │ ├── build.sh │ ├── cibuild.sh │ ├── core-templates │ ├── job │ │ ├── job.yml │ │ ├── onelocbuild.yml │ │ ├── publish-build-assets.yml │ │ ├── source-build.yml │ │ └── source-index-stage1.yml │ ├── jobs │ │ ├── codeql-build.yml │ │ ├── jobs.yml │ │ └── source-build.yml │ ├── post-build │ │ ├── common-variables.yml │ │ ├── post-build.yml │ │ └── setup-maestro-vars.yml │ ├── steps │ │ ├── cleanup-microbuild.yml │ │ ├── component-governance.yml │ │ ├── enable-internal-runtimes.yml │ │ ├── enable-internal-sources.yml │ │ ├── generate-sbom.yml │ │ ├── get-delegation-sas.yml │ │ ├── get-federated-access-token.yml │ │ ├── install-microbuild.yml │ │ ├── publish-build-artifacts.yml │ │ ├── publish-logs.yml │ │ ├── publish-pipeline-artifacts.yml │ │ ├── retain-build.yml │ │ ├── send-to-helix.yml │ │ ├── source-build.yml │ │ └── source-index-stage1-publish.yml │ └── variables │ │ └── pool-providers.yml │ ├── cross │ ├── arm │ │ └── tizen │ │ │ └── tizen.patch │ ├── arm64 │ │ └── tizen │ │ │ └── tizen.patch │ ├── armel │ │ └── tizen │ │ │ └── tizen.patch │ ├── build-android-rootfs.sh │ ├── build-rootfs.sh │ ├── install-debs.py │ ├── riscv64 │ │ └── tizen │ │ │ └── tizen.patch │ ├── tizen-build-rootfs.sh │ ├── tizen-fetch.sh │ ├── toolchain.cmake │ ├── x64 │ │ └── tizen │ │ │ └── tizen.patch │ └── x86 │ │ └── tizen │ │ └── tizen.patch │ ├── darc-init.ps1 │ ├── darc-init.sh │ ├── dotnet-install.cmd │ ├── dotnet-install.ps1 │ ├── dotnet-install.sh │ ├── enable-cross-org-publishing.ps1 │ ├── generate-locproject.ps1 │ ├── generate-sbom-prep.ps1 │ ├── generate-sbom-prep.sh │ ├── helixpublish.proj │ ├── init-tools-native.cmd │ ├── init-tools-native.ps1 │ ├── init-tools-native.sh │ ├── internal-feed-operations.ps1 │ ├── internal-feed-operations.sh │ ├── internal │ ├── Directory.Build.props │ ├── NuGet.config │ └── Tools.csproj │ ├── loc │ └── P22DotNetHtmlLocalization.lss │ ├── msbuild.ps1 │ ├── msbuild.sh │ ├── native │ ├── CommonLibrary.psm1 │ ├── common-library.sh │ ├── init-compiler.sh │ ├── init-distro-rid.sh │ ├── init-os-and-arch.sh │ ├── install-cmake-test.sh │ ├── install-cmake.sh │ ├── install-dependencies.sh │ └── install-tool.ps1 │ ├── pipeline-logging-functions.ps1 │ ├── pipeline-logging-functions.sh │ ├── post-build │ ├── check-channel-consistency.ps1 │ ├── nuget-validation.ps1 │ ├── nuget-verification.ps1 │ ├── publish-using-darc.ps1 │ ├── redact-logs.ps1 │ ├── sourcelink-validation.ps1 │ └── symbols-validation.ps1 │ ├── retain-build.ps1 │ ├── sdk-task.ps1 │ ├── sdk-task.sh │ ├── sdl │ ├── NuGet.config │ ├── configure-sdl-tool.ps1 │ ├── execute-all-sdl-tools.ps1 │ ├── extract-artifact-archives.ps1 │ ├── extract-artifact-packages.ps1 │ ├── init-sdl.ps1 │ ├── packages.config │ ├── run-sdl.ps1 │ ├── sdl.ps1 │ └── trim-assets-version.ps1 │ ├── template-guidance.md │ ├── templates-official │ ├── job │ │ ├── job.yml │ │ ├── onelocbuild.yml │ │ ├── publish-build-assets.yml │ │ ├── source-build.yml │ │ └── source-index-stage1.yml │ ├── jobs │ │ ├── codeql-build.yml │ │ ├── jobs.yml │ │ └── source-build.yml │ ├── post-build │ │ ├── common-variables.yml │ │ ├── post-build.yml │ │ └── setup-maestro-vars.yml │ ├── steps │ │ ├── component-governance.yml │ │ ├── enable-internal-runtimes.yml │ │ ├── enable-internal-sources.yml │ │ ├── generate-sbom.yml │ │ ├── get-delegation-sas.yml │ │ ├── get-federated-access-token.yml │ │ ├── publish-build-artifacts.yml │ │ ├── publish-logs.yml │ │ ├── publish-pipeline-artifacts.yml │ │ ├── retain-build.yml │ │ ├── send-to-helix.yml │ │ ├── source-build.yml │ │ └── source-index-stage1-publish.yml │ └── variables │ │ ├── pool-providers.yml │ │ └── sdl-variables.yml │ ├── templates │ ├── job │ │ ├── job.yml │ │ ├── onelocbuild.yml │ │ ├── publish-build-assets.yml │ │ ├── source-build.yml │ │ └── source-index-stage1.yml │ ├── jobs │ │ ├── codeql-build.yml │ │ ├── jobs.yml │ │ └── source-build.yml │ ├── post-build │ │ ├── common-variables.yml │ │ ├── post-build.yml │ │ └── setup-maestro-vars.yml │ ├── steps │ │ ├── component-governance.yml │ │ ├── enable-internal-runtimes.yml │ │ ├── enable-internal-sources.yml │ │ ├── generate-sbom.yml │ │ ├── get-delegation-sas.yml │ │ ├── get-federated-access-token.yml │ │ ├── publish-build-artifacts.yml │ │ ├── publish-logs.yml │ │ ├── publish-pipeline-artifacts.yml │ │ ├── retain-build.yml │ │ ├── send-to-helix.yml │ │ ├── source-build.yml │ │ ├── source-index-stage1-publish.yml │ │ └── vmr-sync.yml │ ├── variables │ │ └── pool-providers.yml │ └── vmr-build-pr.yml │ ├── tools.ps1 │ ├── tools.sh │ ├── vmr-sync.ps1 │ └── vmr-sync.sh ├── global.json ├── hotreload-utils.proj ├── src ├── Common │ └── TempDirectory.cs ├── Microsoft.DotNet.HotReload.Utils.Generator.BuildTool │ ├── Microsoft.DotNet.HotReload.Utils.Generator.BuildTool.csproj │ ├── Microsoft.DotNet.HotReload.Utils.Generator.BuildTool.targets.in │ ├── Program.cs │ └── README.md ├── Microsoft.DotNet.HotReload.Utils.Generator.Data │ ├── Microsoft.DotNet.HotReload.Utils.Generator.Data.csproj │ ├── OutputSummary │ │ └── OutputSummary.cs │ ├── Script │ │ └── Json │ │ │ ├── Script.cs │ │ │ └── ScriptCapabilitiesConverter.cs │ └── UpdateHandlerInfo.cs ├── Microsoft.DotNet.HotReload.Utils.Generator.Frontend │ ├── Frontend.cs │ └── Microsoft.DotNet.HotReload.Utils.Generator.Frontend.csproj ├── Microsoft.DotNet.HotReload.Utils.Generator.Tasks │ ├── HotReloadDeltaGeneratorComputeScriptOutputs.cs │ └── Microsoft.DotNet.HotReload.Utils.Generator.Tasks.csproj ├── Microsoft.DotNet.HotReload.Utils.Generator │ ├── BaselineArtifacts.cs │ ├── BaselineProject.cs │ ├── Config.cs │ ├── Delta.cs │ ├── DeltaNaming.cs │ ├── DeltaOutputStreams.cs │ ├── DeltaProject.cs │ ├── DiffyException.cs │ ├── DocResolver.cs │ ├── EditAndContinueCapabilitiesParser.cs │ ├── EnC │ │ ├── ChangeMaker.cs │ │ ├── ChangeMakerService.cs │ │ └── EditAndContinueCapabilities.cs │ ├── Microsoft.DotNet.HotReload.Utils.Generator.csproj │ ├── Plan │ │ └── Change.cs │ ├── Runner.cs │ ├── Runners │ │ ├── LiveRunner.cs │ │ └── ScriptRunner.cs │ ├── Script │ │ ├── Json │ │ │ └── Parsing.cs │ │ └── ParsedScript.cs │ └── Util │ │ ├── AsyncEnumerableExtras.cs │ │ └── FSWGen.cs └── hotreload-delta-gen │ ├── README.md │ ├── example │ ├── TestClass.cs │ ├── TestClass.csproj │ ├── TestClass_v1.cs │ ├── TestClass_v2.cs │ ├── TestClass_v3.cs │ └── diffscript.json │ └── src │ ├── Program.cs │ └── hotreload-delta-gen.csproj └── tests ├── Acceptance └── EncCapabilitiesCompat.Tests │ ├── EncCapabilitiesCompat.Tests.csproj │ └── EncCapabilitiesCompat.cs ├── BuildTool ├── ImportExplcitly.ShouldNotRun.Tests │ ├── ImportExplicitly.ShouldNotRun.Tests.csproj │ └── ImportExplicitly.ShouldNotRun.cs ├── ImportExplcitly.Tests │ ├── ImportExplicitly.Tests.csproj │ ├── ImportExplicitly.cs │ ├── TargetClass.cs │ ├── TargetClass.cs.v1 │ └── delta.json └── ImportExplicitly.props └── HotReload.Generator ├── EnC.Tests ├── Assembly.NoParallelism.cs ├── CommonFixtures.cs ├── EnC.Tests.csproj ├── TempMSBuildWorkspaceTest.cs └── WatchHotReloadServiceTest.cs └── README.md /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 4 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | # Xml project files 11 | [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}] 12 | indent_size = 2 13 | 14 | # Xml config files 15 | [*.{props,targets,config,nuspec}] 16 | indent_size = 2 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .dotnet/ 2 | .packages/ 3 | Output/ 4 | artifacts/ 5 | bin/ 6 | obj/ 7 | publish/ 8 | *~ 9 | *.dll 10 | *.pdb 11 | *.dil 12 | *.dmeta 13 | *.dpdb 14 | /.vscode/ 15 | /out/ 16 | -------------------------------------------------------------------------------- /CODE-OF-CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | This project has adopted the code of conduct defined by the Contributor Covenant 4 | to clarify expected behavior in our community. 5 | 6 | For more information, see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct). 7 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | $(CopyrightNetFoundation) 7 | MIT 8 | True 9 | embedded 10 | true 11 | Latest 12 | $(NetCurrent) 13 | enable 14 | 15 | 18 | false 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Directory.Build.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) .NET Foundation and Contributors 4 | 5 | All rights reserved. 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Hot Reload Utilities # 2 | 3 | Testing utilities for ".NET Hot Reload". 4 | 5 | ## What's in here ## 6 | 7 | - [Microsoft.DotNet.HotReload.Utils.Generator.BuildTool](src/Microsoft.DotNet.HotReload.Utils.Generator.BuildTool/) - MSBuild integration package to generate deltas from a script of changes. This is what you want for CI testing. ([README.md](src/Microsoft.DotNet.HotReload.Utils.Generator.BuildTool/README.md)) 8 | 9 | 10 | - [Microsoft.DotNet.HotReload.Utils.Generator](src/Microsoft.DotNet.HotReload.Utils.Generator/) - A library for creating tools that generate hot reload deltas. 11 | - [hotreload-delta-gen](src/hotreload-delta-gen/) - A script-driven delta generator packaged as a `dotnet tool`. This is mostly useful for experimentation. ([README.md](src/hotreload-delta-gen/README.md)) 12 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)), please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /THIRD-PARTY-NOTICES.txt: -------------------------------------------------------------------------------- 1 | .NET Runtime uses third-party libraries or other resources that may be 2 | distributed under licenses different than the .NET Runtime software. 3 | 4 | In the event that we accidentally failed to list a required notice, please 5 | bring it to our attention. Post an issue or email us: 6 | 7 | dotnet@microsoft.com 8 | 9 | The attached notices are provided for information only. 10 | 11 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | 5 | # resolve $SOURCE until the file is no longer a symlink 6 | while [[ -h $source ]]; do 7 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 8 | source="$(readlink "$source")" 9 | 10 | # if $source was a relative symlink, we need to resolve it relative to the path where the 11 | # symlink file was located 12 | [[ $source != /* ]] && source="$scriptroot/$source" 13 | done 14 | 15 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 16 | 17 | "$scriptroot/eng/common/build.sh" $@ 18 | 19 | -------------------------------------------------------------------------------- /dotnet.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | # resolve $SOURCE until the file is no longer a symlink 5 | while [[ -h $source ]]; do 6 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 7 | source="$(readlink "$source")" 8 | 9 | # if $source was a relative symlink, we need to resolve it relative to the path where the 10 | # symlink file was located 11 | [[ $source != /* ]] && source="$scriptroot/$source" 12 | done 13 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 14 | 15 | # Don't resolve runtime, shared framework, or SDK from other locations to ensure build determinism 16 | export DOTNET_MULTILEVEL_LOOKUP=0 17 | 18 | # Disable first run since we want to control all package sources 19 | export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 20 | 21 | source $scriptroot/eng/common/tools.sh 22 | 23 | InitializeDotNetCli true # Install 24 | __dotnetDir=${_InitializeDotNetCli} 25 | 26 | dotnetPath=${__dotnetDir}/dotnet 27 | ${dotnetPath} "$@" 28 | -------------------------------------------------------------------------------- /eng/Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /eng/Publishing.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 3 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /eng/Version.Details.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | https://github.com/dotnet/roslyn 6 | 1119c85de2f6e18124cb27816c5fb189af0745a4 7 | 8 | 9 | 10 | 11 | https://github.com/dotnet/arcade 12 | aba421eb78276b26d1a24df7772474806b27aa13 13 | 14 | 15 | https://github.com/dotnet/arcade 16 | aba421eb78276b26d1a24df7772474806b27aa13 17 | 18 | 19 | https://github.com/dotnet/arcade 20 | aba421eb78276b26d1a24df7772474806b27aa13 21 | 22 | 23 | https://github.com/dotnet/arcade 24 | aba421eb78276b26d1a24df7772474806b27aa13 25 | 26 | 27 | https://github.com/dotnet/arcade 28 | aba421eb78276b26d1a24df7772474806b27aa13 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /eng/Versions.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10.0.0 6 | 7 | alpha 8 | 9 | 0 10 | 11 | false 12 | 13 | 3.11.0 14 | 5.0.0-1.25308.2 15 | 16 | 10.0.0-beta.25305.3 17 | 10.0.0-beta.25305.3 18 | 10.0.0-beta.25305.3 19 | 2.9.2-beta.25305.3 20 | 24 | 17.11.4 25 | $(RefOnlyMicrosoftBuildVersion) 26 | $(RefOnlyMicrosoftBuildVersion) 27 | $(RefOnlyMicrosoftBuildVersion) 28 | 29 | 30 | -------------------------------------------------------------------------------- /eng/azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | variables: 2 | - template: /eng/common/templates/variables/pool-providers.yml 3 | - name: Build.Repository.Clean 4 | value: true 5 | - name: _TeamName 6 | value: DotNetCore 7 | - name: _InternalBuildArgs 8 | value: '' 9 | - name: _InternalPublishArg 10 | value: '' 11 | 12 | - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: 13 | - name: _SignType 14 | value: real 15 | # Publish-Build-Assets provides: MaestroAccessToken, BotAccount-dotnet-maestro-bot-PAT 16 | # DotNet-HelixApi-Access provides: HelixApiAccessToken 17 | - group: Publish-Build-Assets 18 | - group: DotNet-HelixApi-Access 19 | - group: SDL_Settings 20 | - name: _InternalPublishArg 21 | value: -publish 22 | - name: _InternalBuildArgs 23 | value: /p:DotNetSignType=$(_SignType) 24 | /p:TeamName=$(_TeamName) 25 | /p:DotNetPublishUsingPipelines=true 26 | /p:OfficialBuildId=$(BUILD.BUILDNUMBER) 27 | 28 | trigger: 29 | batch: true 30 | branches: 31 | include: 32 | - main 33 | - release/* 34 | 35 | pr: 36 | branches: 37 | include: 38 | - main 39 | - release/* 40 | 41 | stages: 42 | - stage: build 43 | displayName: Build 44 | jobs: 45 | - template: /eng/common/templates/jobs/jobs.yml 46 | parameters: 47 | enablePublishBuildArtifacts: true 48 | enablePublishBuildAssets: true 49 | enablePublishUsingPipelines: true 50 | variables: 51 | - _BuildConfig: Release 52 | jobs: 53 | - job: Build_Linux 54 | displayName: Linux 55 | timeoutInMinutes: 30 56 | pool: 57 | ${{ if eq(variables['System.TeamProject'], 'public') }}: 58 | name: $(DncEngPublicBuildPool) 59 | demands: ImageOverride -equals build.ubuntu.2204.amd64.open 60 | ${{ if eq(variables['System.TeamProject'], 'internal') }}: 61 | name: $(DncEngInternalBuildPool) 62 | demands: ImageOverride -equals build.ubuntu.2204.amd64 63 | steps: 64 | - bash: | 65 | eng/common/cibuild.sh -configuration $(_BuildConfig) $(_InternalPublishArg) /p:ToolConfiguration=$(_BuildConfig) /p:ToolRid=linux-x64 $(_InternalBuildArgs) 66 | displayName: Build and Publish 67 | 68 | - task: PublishTestResults@2 69 | displayName: Publish Test Results 70 | inputs: 71 | testRunner: XUnit 72 | testResultsFiles: 'artifacts/TestResults/$(_BuildConfig)/*.xml' 73 | mergeTestResults: true 74 | testRunTitle: 'Unit Tests' 75 | condition: always() 76 | 77 | ############ POST BUILD ARCADE LOGIC ############ 78 | - ${{ if and(ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: 79 | - template: /eng/common/templates/post-build/post-build.yml 80 | parameters: 81 | publishingInfraVersion: 3 82 | enableSourceLinkValidation: true 83 | enableSigningValidation: false 84 | enableSymbolValidation: false 85 | enableNugetValidation: true 86 | -------------------------------------------------------------------------------- /eng/common/BuildConfiguration/build-configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "RetryCountLimit": 1, 3 | "RetryByAnyError": false 4 | } 5 | -------------------------------------------------------------------------------- /eng/common/CIBuild.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0Build.ps1""" -restore -build -test -sign -pack -publish -ci %*" 3 | -------------------------------------------------------------------------------- /eng/common/PSScriptAnalyzerSettings.psd1: -------------------------------------------------------------------------------- 1 | @{ 2 | IncludeRules=@('PSAvoidUsingCmdletAliases', 3 | 'PSAvoidUsingWMICmdlet', 4 | 'PSAvoidUsingPositionalParameters', 5 | 'PSAvoidUsingInvokeExpression', 6 | 'PSUseDeclaredVarsMoreThanAssignments', 7 | 'PSUseCmdletCorrectly', 8 | 'PSStandardDSCFunctionsInResource', 9 | 'PSUseIdenticalMandatoryParametersForDSC', 10 | 'PSUseIdenticalParametersForDSC') 11 | } -------------------------------------------------------------------------------- /eng/common/README.md: -------------------------------------------------------------------------------- 1 | # Don't touch this folder 2 | 3 | uuuuuuuuuuuuuuuuuuuu 4 | u" uuuuuuuuuuuuuuuuuu "u 5 | u" u$$$$$$$$$$$$$$$$$$$$u "u 6 | u" u$$$$$$$$$$$$$$$$$$$$$$$$u "u 7 | u" u$$$$$$$$$$$$$$$$$$$$$$$$$$$$u "u 8 | u" u$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$u "u 9 | u" u$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$u "u 10 | $ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $ 11 | $ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $ 12 | $ $$$" ... "$... ...$" ... "$$$ ... "$$$ $ 13 | $ $$$u `"$$$$$$$ $$$ $$$$$ $$ $$$ $$$ $ 14 | $ $$$$$$uu "$$$$ $$$ $$$$$ $$ """ u$$$ $ 15 | $ $$$""$$$ $$$$ $$$u "$$$" u$$ $$$$$$$$ $ 16 | $ $$$$....,$$$$$..$$$$$....,$$$$..$$$$$$$$ $ 17 | $ $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $ 18 | "u "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" u" 19 | "u "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$" u" 20 | "u "$$$$$$$$$$$$$$$$$$$$$$$$$$$$" u" 21 | "u "$$$$$$$$$$$$$$$$$$$$$$$$" u" 22 | "u "$$$$$$$$$$$$$$$$$$$$" u" 23 | "u """""""""""""""""" u" 24 | """""""""""""""""""" 25 | 26 | !!! Changes made in this directory are subject to being overwritten by automation !!! 27 | 28 | The files in this directory are shared by all Arcade repos and managed by automation. If you need to make changes to these files, open an issue or submit a pull request to https://github.com/dotnet/arcade first. 29 | -------------------------------------------------------------------------------- /eng/common/build.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0build.ps1""" %*" 3 | exit /b %ErrorLevel% 4 | -------------------------------------------------------------------------------- /eng/common/cibuild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | 5 | # resolve $SOURCE until the file is no longer a symlink 6 | while [[ -h $source ]]; do 7 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 8 | source="$(readlink "$source")" 9 | 10 | # if $source was a relative symlink, we need to resolve it relative to the path where 11 | # the symlink file was located 12 | [[ $source != /* ]] && source="$scriptroot/$source" 13 | done 14 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 15 | 16 | . "$scriptroot/build.sh" --restore --build --test --pack --publish --ci $@ 17 | -------------------------------------------------------------------------------- /eng/common/core-templates/job/source-index-stage1.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | runAsPublic: false 3 | sourceIndexBuildCommand: powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -Command "eng/common/build.ps1 -restore -build -binarylog -ci" 4 | preSteps: [] 5 | binlogPath: artifacts/log/Debug/Build.binlog 6 | condition: '' 7 | dependsOn: '' 8 | pool: '' 9 | is1ESPipeline: '' 10 | 11 | jobs: 12 | - job: SourceIndexStage1 13 | dependsOn: ${{ parameters.dependsOn }} 14 | condition: ${{ parameters.condition }} 15 | variables: 16 | - name: BinlogPath 17 | value: ${{ parameters.binlogPath }} 18 | - template: /eng/common/core-templates/variables/pool-providers.yml 19 | parameters: 20 | is1ESPipeline: ${{ parameters.is1ESPipeline }} 21 | 22 | ${{ if ne(parameters.pool, '') }}: 23 | pool: ${{ parameters.pool }} 24 | ${{ if eq(parameters.pool, '') }}: 25 | pool: 26 | ${{ if eq(variables['System.TeamProject'], 'public') }}: 27 | name: $(DncEngPublicBuildPool) 28 | image: windows.vs2022.amd64.open 29 | ${{ if eq(variables['System.TeamProject'], 'internal') }}: 30 | name: $(DncEngInternalBuildPool) 31 | image: windows.vs2022.amd64 32 | 33 | steps: 34 | - ${{ if eq(parameters.is1ESPipeline, '') }}: 35 | - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error 36 | 37 | - ${{ each preStep in parameters.preSteps }}: 38 | - ${{ preStep }} 39 | - script: ${{ parameters.sourceIndexBuildCommand }} 40 | displayName: Build Repository 41 | 42 | - template: /eng/common/core-templates/steps/source-index-stage1-publish.yml 43 | parameters: 44 | binLogPath: ${{ parameters.binLogPath }} -------------------------------------------------------------------------------- /eng/common/core-templates/jobs/codeql-build.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | # See schema documentation in /Documentation/AzureDevOps/TemplateSchema.md 3 | continueOnError: false 4 | # Required: A collection of jobs to run - https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=vsts&tabs=schema#job 5 | jobs: [] 6 | # Optional: if specified, restore and use this version of Guardian instead of the default. 7 | overrideGuardianVersion: '' 8 | is1ESPipeline: '' 9 | 10 | jobs: 11 | - template: /eng/common/core-templates/jobs/jobs.yml 12 | parameters: 13 | is1ESPipeline: ${{ parameters.is1ESPipeline }} 14 | enableMicrobuild: false 15 | enablePublishBuildArtifacts: false 16 | enablePublishTestResults: false 17 | enablePublishBuildAssets: false 18 | enableTelemetry: true 19 | 20 | variables: 21 | - group: Publish-Build-Assets 22 | # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in 23 | # sync with the packages.config file. 24 | - name: DefaultGuardianVersion 25 | value: 0.109.0 26 | - name: GuardianPackagesConfigFile 27 | value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config 28 | - name: GuardianVersion 29 | value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }} 30 | 31 | jobs: ${{ parameters.jobs }} 32 | 33 | -------------------------------------------------------------------------------- /eng/common/core-templates/jobs/source-build.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | # This template adds arcade-powered source-build to CI. A job is created for each platform, as 3 | # well as an optional server job that completes when all platform jobs complete. 4 | 5 | # The name of the "join" job for all source-build platforms. If set to empty string, the job is 6 | # not included. Existing repo pipelines can use this job depend on all source-build jobs 7 | # completing without maintaining a separate list of every single job ID: just depend on this one 8 | # server job. By default, not included. Recommended name if used: 'Source_Build_Complete'. 9 | allCompletedJobId: '' 10 | 11 | # See /eng/common/core-templates/job/source-build.yml 12 | jobNamePrefix: 'Source_Build' 13 | 14 | # This is the default platform provided by Arcade, intended for use by a managed-only repo. 15 | defaultManagedPlatform: 16 | name: 'Managed' 17 | container: 'mcr.microsoft.com/dotnet-buildtools/prereqs:centos-stream-10-amd64' 18 | 19 | # Defines the platforms on which to run build jobs. One job is created for each platform, and the 20 | # object in this array is sent to the job template as 'platform'. If no platforms are specified, 21 | # one job runs on 'defaultManagedPlatform'. 22 | platforms: [] 23 | 24 | is1ESPipeline: '' 25 | 26 | # If set to true and running on a non-public project, 27 | # Internal nuget and blob storage locations will be enabled. 28 | # This is not enabled by default because many repositories do not need internal sources 29 | # and do not need to have the required service connections approved in the pipeline. 30 | enableInternalSources: false 31 | 32 | jobs: 33 | 34 | - ${{ if ne(parameters.allCompletedJobId, '') }}: 35 | - job: ${{ parameters.allCompletedJobId }} 36 | displayName: Source-Build Complete 37 | pool: server 38 | dependsOn: 39 | - ${{ each platform in parameters.platforms }}: 40 | - ${{ parameters.jobNamePrefix }}_${{ platform.name }} 41 | - ${{ if eq(length(parameters.platforms), 0) }}: 42 | - ${{ parameters.jobNamePrefix }}_${{ parameters.defaultManagedPlatform.name }} 43 | 44 | - ${{ each platform in parameters.platforms }}: 45 | - template: /eng/common/core-templates/job/source-build.yml 46 | parameters: 47 | is1ESPipeline: ${{ parameters.is1ESPipeline }} 48 | jobNamePrefix: ${{ parameters.jobNamePrefix }} 49 | platform: ${{ platform }} 50 | enableInternalSources: ${{ parameters.enableInternalSources }} 51 | 52 | - ${{ if eq(length(parameters.platforms), 0) }}: 53 | - template: /eng/common/core-templates/job/source-build.yml 54 | parameters: 55 | is1ESPipeline: ${{ parameters.is1ESPipeline }} 56 | jobNamePrefix: ${{ parameters.jobNamePrefix }} 57 | platform: ${{ parameters.defaultManagedPlatform }} 58 | enableInternalSources: ${{ parameters.enableInternalSources }} 59 | -------------------------------------------------------------------------------- /eng/common/core-templates/post-build/common-variables.yml: -------------------------------------------------------------------------------- 1 | variables: 2 | - group: Publish-Build-Assets 3 | 4 | # Whether the build is internal or not 5 | - name: IsInternalBuild 6 | value: ${{ and(ne(variables['System.TeamProject'], 'public'), contains(variables['Build.SourceBranch'], 'internal')) }} 7 | 8 | # Default Maestro++ API Endpoint and API Version 9 | - name: MaestroApiEndPoint 10 | value: "https://maestro.dot.net" 11 | - name: MaestroApiVersion 12 | value: "2020-02-20" 13 | 14 | - name: SourceLinkCLIVersion 15 | value: 3.0.0 16 | - name: SymbolToolVersion 17 | value: 1.0.1 18 | - name: BinlogToolVersion 19 | value: 1.0.11 20 | 21 | - name: runCodesignValidationInjection 22 | value: false 23 | -------------------------------------------------------------------------------- /eng/common/core-templates/post-build/setup-maestro-vars.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | BARBuildId: '' 3 | PromoteToChannelIds: '' 4 | is1ESPipeline: '' 5 | 6 | steps: 7 | - ${{ if eq(parameters.is1ESPipeline, '') }}: 8 | - 'Illegal entry point, is1ESPipeline is not defined. Repository yaml should not directly reference templates in core-templates folder.': error 9 | 10 | - ${{ if eq(coalesce(parameters.PromoteToChannelIds, 0), 0) }}: 11 | - task: DownloadBuildArtifacts@0 12 | displayName: Download Release Configs 13 | inputs: 14 | buildType: current 15 | artifactName: ReleaseConfigs 16 | checkDownloadedFiles: true 17 | 18 | - task: AzureCLI@2 19 | name: setReleaseVars 20 | displayName: Set Release Configs Vars 21 | inputs: 22 | azureSubscription: "Darc: Maestro Production" 23 | scriptType: pscore 24 | scriptLocation: inlineScript 25 | inlineScript: | 26 | try { 27 | if (!$Env:PromoteToMaestroChannels -or $Env:PromoteToMaestroChannels.Trim() -eq '') { 28 | $Content = Get-Content $(Build.StagingDirectory)/ReleaseConfigs/ReleaseConfigs.txt 29 | 30 | $BarId = $Content | Select -Index 0 31 | $Channels = $Content | Select -Index 1 32 | $IsStableBuild = $Content | Select -Index 2 33 | 34 | $AzureDevOpsProject = $Env:System_TeamProject 35 | $AzureDevOpsBuildDefinitionId = $Env:System_DefinitionId 36 | $AzureDevOpsBuildId = $Env:Build_BuildId 37 | } 38 | else { 39 | . $(Build.SourcesDirectory)\eng\common\tools.ps1 40 | $darc = Get-Darc 41 | $buildInfo = & $darc get-build ` 42 | --id ${{ parameters.BARBuildId }} ` 43 | --extended ` 44 | --output-format json ` 45 | --ci ` 46 | | convertFrom-Json 47 | 48 | $BarId = ${{ parameters.BARBuildId }} 49 | $Channels = $Env:PromoteToMaestroChannels -split "," 50 | $Channels = $Channels -join "][" 51 | $Channels = "[$Channels]" 52 | 53 | $IsStableBuild = $buildInfo.stable 54 | $AzureDevOpsProject = $buildInfo.azureDevOpsProject 55 | $AzureDevOpsBuildDefinitionId = $buildInfo.azureDevOpsBuildDefinitionId 56 | $AzureDevOpsBuildId = $buildInfo.azureDevOpsBuildId 57 | } 58 | 59 | Write-Host "##vso[task.setvariable variable=BARBuildId]$BarId" 60 | Write-Host "##vso[task.setvariable variable=TargetChannels]$Channels" 61 | Write-Host "##vso[task.setvariable variable=IsStableBuild]$IsStableBuild" 62 | 63 | Write-Host "##vso[task.setvariable variable=AzDOProjectName]$AzureDevOpsProject" 64 | Write-Host "##vso[task.setvariable variable=AzDOPipelineId]$AzureDevOpsBuildDefinitionId" 65 | Write-Host "##vso[task.setvariable variable=AzDOBuildId]$AzureDevOpsBuildId" 66 | } 67 | catch { 68 | Write-Host $_ 69 | Write-Host $_.Exception 70 | Write-Host $_.ScriptStackTrace 71 | exit 1 72 | } 73 | env: 74 | PromoteToMaestroChannels: ${{ parameters.PromoteToChannelIds }} 75 | -------------------------------------------------------------------------------- /eng/common/core-templates/steps/cleanup-microbuild.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | # Enable cleanup tasks for MicroBuild 3 | enableMicrobuild: false 4 | # Enable cleanup tasks for MicroBuild on Mac and Linux 5 | # Will be ignored if 'enableMicrobuild' is false or 'Agent.Os' is 'Windows_NT' 6 | enableMicrobuildForMacAndLinux: false 7 | continueOnError: false 8 | 9 | steps: 10 | - ${{ if eq(parameters.enableMicrobuild, 'true') }}: 11 | - task: MicroBuildCleanup@1 12 | displayName: Execute Microbuild cleanup tasks 13 | condition: and( 14 | always(), 15 | or( 16 | and( 17 | eq(variables['Agent.Os'], 'Windows_NT'), 18 | in(variables['_SignType'], 'real', 'test') 19 | ), 20 | and( 21 | ${{ eq(parameters.enableMicrobuildForMacAndLinux, true) }}, 22 | ne(variables['Agent.Os'], 'Windows_NT'), 23 | eq(variables['_SignType'], 'real') 24 | ) 25 | )) 26 | continueOnError: ${{ parameters.continueOnError }} 27 | env: 28 | TeamName: $(_TeamName) 29 | -------------------------------------------------------------------------------- /eng/common/core-templates/steps/component-governance.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | disableComponentGovernance: false 3 | componentGovernanceIgnoreDirectories: '' 4 | is1ESPipeline: false 5 | displayName: 'Component Detection' 6 | 7 | steps: 8 | - ${{ if eq(parameters.disableComponentGovernance, 'true') }}: 9 | - script: echo "##vso[task.setvariable variable=skipComponentGovernanceDetection]true" 10 | displayName: Set skipComponentGovernanceDetection variable 11 | - ${{ if ne(parameters.disableComponentGovernance, 'true') }}: 12 | - task: ComponentGovernanceComponentDetection@0 13 | continueOnError: true 14 | displayName: ${{ parameters.displayName }} 15 | inputs: 16 | ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }} 17 | -------------------------------------------------------------------------------- /eng/common/core-templates/steps/enable-internal-runtimes.yml: -------------------------------------------------------------------------------- 1 | # Obtains internal runtime download credentials and populates the 'dotnetbuilds-internal-container-read-token-base64' 2 | # variable with the base64-encoded SAS token, by default 3 | 4 | parameters: 5 | - name: federatedServiceConnection 6 | type: string 7 | default: 'dotnetbuilds-internal-read' 8 | - name: outputVariableName 9 | type: string 10 | default: 'dotnetbuilds-internal-container-read-token-base64' 11 | - name: expiryInHours 12 | type: number 13 | default: 1 14 | - name: base64Encode 15 | type: boolean 16 | default: true 17 | - name: is1ESPipeline 18 | type: boolean 19 | default: false 20 | 21 | steps: 22 | - ${{ if ne(variables['System.TeamProject'], 'public') }}: 23 | - template: /eng/common/core-templates/steps/get-delegation-sas.yml 24 | parameters: 25 | federatedServiceConnection: ${{ parameters.federatedServiceConnection }} 26 | outputVariableName: ${{ parameters.outputVariableName }} 27 | expiryInHours: ${{ parameters.expiryInHours }} 28 | base64Encode: ${{ parameters.base64Encode }} 29 | storageAccount: dotnetbuilds 30 | container: internal 31 | permissions: rl 32 | is1ESPipeline: ${{ parameters.is1ESPipeline }} -------------------------------------------------------------------------------- /eng/common/core-templates/steps/enable-internal-sources.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | # This is the Azure federated service connection that we log into to get an access token. 3 | - name: nugetFederatedServiceConnection 4 | type: string 5 | default: 'dnceng-artifacts-feeds-read' 6 | - name: is1ESPipeline 7 | type: boolean 8 | default: false 9 | # Legacy parameters to allow for PAT usage 10 | - name: legacyCredential 11 | type: string 12 | default: '' 13 | 14 | steps: 15 | - ${{ if ne(variables['System.TeamProject'], 'public') }}: 16 | - ${{ if ne(parameters.legacyCredential, '') }}: 17 | - task: PowerShell@2 18 | displayName: Setup Internal Feeds 19 | inputs: 20 | filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1 21 | arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $Env:Token 22 | env: 23 | Token: ${{ parameters.legacyCredential }} 24 | # If running on dnceng (internal project), just use the default behavior for NuGetAuthenticate. 25 | # If running on DevDiv, NuGetAuthenticate is not really an option. It's scoped to a single feed, and we have many feeds that 26 | # may be added. Instead, we'll use the traditional approach (add cred to nuget.config), but use an account token. 27 | - ${{ else }}: 28 | - ${{ if eq(variables['System.TeamProject'], 'internal') }}: 29 | - task: PowerShell@2 30 | displayName: Setup Internal Feeds 31 | inputs: 32 | filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1 33 | arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config 34 | - ${{ else }}: 35 | - template: /eng/common/templates/steps/get-federated-access-token.yml 36 | parameters: 37 | federatedServiceConnection: ${{ parameters.nugetFederatedServiceConnection }} 38 | outputVariableName: 'dnceng-artifacts-feeds-read-access-token' 39 | - task: PowerShell@2 40 | displayName: Setup Internal Feeds 41 | inputs: 42 | filePath: $(Build.SourcesDirectory)/eng/common/SetupNugetSources.ps1 43 | arguments: -ConfigFile $(Build.SourcesDirectory)/NuGet.config -Password $(dnceng-artifacts-feeds-read-access-token) 44 | # This is required in certain scenarios to install the ADO credential provider. 45 | # It installed by default in some msbuild invocations (e.g. VS msbuild), but needs to be installed for others 46 | # (e.g. dotnet msbuild). 47 | - task: NuGetAuthenticate@1 48 | -------------------------------------------------------------------------------- /eng/common/core-templates/steps/generate-sbom.yml: -------------------------------------------------------------------------------- 1 | # BuildDropPath - The root folder of the drop directory for which the manifest file will be generated. 2 | # PackageName - The name of the package this SBOM represents. 3 | # PackageVersion - The version of the package this SBOM represents. 4 | # ManifestDirPath - The path of the directory where the generated manifest files will be placed 5 | # IgnoreDirectories - Directories to ignore for SBOM generation. This will be passed through to the CG component detector. 6 | 7 | parameters: 8 | PackageVersion: 10.0.0 9 | BuildDropPath: '$(Build.SourcesDirectory)/artifacts' 10 | PackageName: '.NET' 11 | ManifestDirPath: $(Build.ArtifactStagingDirectory)/sbom 12 | IgnoreDirectories: '' 13 | sbomContinueOnError: true 14 | is1ESPipeline: false 15 | # disable publishArtifacts if some other step is publishing the artifacts (like job.yml). 16 | publishArtifacts: true 17 | 18 | steps: 19 | - task: PowerShell@2 20 | displayName: Prep for SBOM generation in (Non-linux) 21 | condition: or(eq(variables['Agent.Os'], 'Windows_NT'), eq(variables['Agent.Os'], 'Darwin')) 22 | inputs: 23 | filePath: ./eng/common/generate-sbom-prep.ps1 24 | arguments: ${{parameters.manifestDirPath}} 25 | 26 | # Chmodding is a workaround for https://github.com/dotnet/arcade/issues/8461 27 | - script: | 28 | chmod +x ./eng/common/generate-sbom-prep.sh 29 | ./eng/common/generate-sbom-prep.sh ${{parameters.manifestDirPath}} 30 | displayName: Prep for SBOM generation in (Linux) 31 | condition: eq(variables['Agent.Os'], 'Linux') 32 | continueOnError: ${{ parameters.sbomContinueOnError }} 33 | 34 | - task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 35 | displayName: 'Generate SBOM manifest' 36 | continueOnError: ${{ parameters.sbomContinueOnError }} 37 | inputs: 38 | PackageName: ${{ parameters.packageName }} 39 | BuildDropPath: ${{ parameters.buildDropPath }} 40 | PackageVersion: ${{ parameters.packageVersion }} 41 | ManifestDirPath: ${{ parameters.manifestDirPath }}/$(ARTIFACT_NAME) 42 | ${{ if ne(parameters.IgnoreDirectories, '') }}: 43 | AdditionalComponentDetectorArgs: '--IgnoreDirectories ${{ parameters.IgnoreDirectories }}' 44 | 45 | - ${{ if eq(parameters.publishArtifacts, 'true')}}: 46 | - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml 47 | parameters: 48 | is1ESPipeline: ${{ parameters.is1ESPipeline }} 49 | args: 50 | displayName: Publish SBOM manifest 51 | continueOnError: ${{parameters.sbomContinueOnError}} 52 | targetPath: '${{ parameters.manifestDirPath }}' 53 | artifactName: $(ARTIFACT_NAME) 54 | 55 | -------------------------------------------------------------------------------- /eng/common/core-templates/steps/get-delegation-sas.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: federatedServiceConnection 3 | type: string 4 | - name: outputVariableName 5 | type: string 6 | - name: expiryInHours 7 | type: number 8 | default: 1 9 | - name: base64Encode 10 | type: boolean 11 | default: false 12 | - name: storageAccount 13 | type: string 14 | - name: container 15 | type: string 16 | - name: permissions 17 | type: string 18 | default: 'rl' 19 | - name: is1ESPipeline 20 | type: boolean 21 | default: false 22 | 23 | steps: 24 | - task: AzureCLI@2 25 | displayName: 'Generate delegation SAS Token for ${{ parameters.storageAccount }}/${{ parameters.container }}' 26 | inputs: 27 | azureSubscription: ${{ parameters.federatedServiceConnection }} 28 | scriptType: 'pscore' 29 | scriptLocation: 'inlineScript' 30 | inlineScript: | 31 | # Calculate the expiration of the SAS token and convert to UTC 32 | $expiry = (Get-Date).AddHours(${{ parameters.expiryInHours }}).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") 33 | 34 | $sas = az storage container generate-sas --account-name ${{ parameters.storageAccount }} --name ${{ parameters.container }} --permissions ${{ parameters.permissions }} --expiry $expiry --auth-mode login --as-user -o tsv 35 | 36 | if ($LASTEXITCODE -ne 0) { 37 | Write-Error "Failed to generate SAS token." 38 | exit 1 39 | } 40 | 41 | if ('${{ parameters.base64Encode }}' -eq 'true') { 42 | $sas = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($sas)) 43 | } 44 | 45 | Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" 46 | Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true]$sas" 47 | -------------------------------------------------------------------------------- /eng/common/core-templates/steps/get-federated-access-token.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: federatedServiceConnection 3 | type: string 4 | - name: outputVariableName 5 | type: string 6 | - name: is1ESPipeline 7 | type: boolean 8 | - name: stepName 9 | type: string 10 | default: 'getFederatedAccessToken' 11 | - name: condition 12 | type: string 13 | default: '' 14 | # Resource to get a token for. Common values include: 15 | # - '499b84ac-1321-427f-aa17-267ca6975798' for Azure DevOps 16 | # - 'https://storage.azure.com/' for storage 17 | # Defaults to Azure DevOps 18 | - name: resource 19 | type: string 20 | default: '499b84ac-1321-427f-aa17-267ca6975798' 21 | - name: isStepOutputVariable 22 | type: boolean 23 | default: false 24 | 25 | steps: 26 | - task: AzureCLI@2 27 | displayName: 'Getting federated access token for feeds' 28 | name: ${{ parameters.stepName }} 29 | ${{ if ne(parameters.condition, '') }}: 30 | condition: ${{ parameters.condition }} 31 | inputs: 32 | azureSubscription: ${{ parameters.federatedServiceConnection }} 33 | scriptType: 'pscore' 34 | scriptLocation: 'inlineScript' 35 | inlineScript: | 36 | $accessToken = az account get-access-token --query accessToken --resource ${{ parameters.resource }} --output tsv 37 | if ($LASTEXITCODE -ne 0) { 38 | Write-Error "Failed to get access token for resource '${{ parameters.resource }}'" 39 | exit 1 40 | } 41 | Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" 42 | Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true;isOutput=${{ parameters.isStepOutputVariable }}]$accessToken" -------------------------------------------------------------------------------- /eng/common/core-templates/steps/install-microbuild.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | # Enable install tasks for MicroBuild 3 | enableMicrobuild: false 4 | # Enable install tasks for MicroBuild on Mac and Linux 5 | # Will be ignored if 'enableMicrobuild' is false or 'Agent.Os' is 'Windows_NT' 6 | enableMicrobuildForMacAndLinux: false 7 | # Location of the MicroBuild output folder 8 | microBuildOutputFolder: '$(Build.SourcesDirectory)' 9 | continueOnError: false 10 | 11 | steps: 12 | - ${{ if eq(parameters.enableMicrobuild, 'true') }}: 13 | - ${{ if eq(parameters.enableMicrobuildForMacAndLinux, 'true') }}: 14 | # Needed to download the MicroBuild plugin nupkgs on Mac and Linux when nuget.exe is unavailable 15 | - task: UseDotNet@2 16 | displayName: Install .NET 8.0 SDK for MicroBuild Plugin 17 | inputs: 18 | packageType: sdk 19 | version: 8.0.x 20 | installationPath: ${{ parameters.microBuildOutputFolder }}/.dotnet 21 | workingDirectory: ${{ parameters.microBuildOutputFolder }} 22 | condition: and(succeeded(), ne(variables['Agent.Os'], 'Windows_NT')) 23 | 24 | - task: MicroBuildSigningPlugin@4 25 | displayName: Install MicroBuild plugin 26 | inputs: 27 | signType: $(_SignType) 28 | zipSources: false 29 | feedSource: https://dnceng.pkgs.visualstudio.com/_packaging/MicroBuildToolset/nuget/v3/index.json 30 | ${{ if and(eq(parameters.enableMicrobuildForMacAndLinux, 'true'), ne(variables['Agent.Os'], 'Windows_NT')) }}: 31 | azureSubscription: 'MicroBuild Signing Task (DevDiv)' 32 | useEsrpCli: true 33 | env: 34 | TeamName: $(_TeamName) 35 | MicroBuildOutputFolderOverride: ${{ parameters.microBuildOutputFolder }} 36 | SYSTEM_ACCESSTOKEN: $(System.AccessToken) 37 | continueOnError: ${{ parameters.continueOnError }} 38 | condition: and( 39 | succeeded(), 40 | or( 41 | and( 42 | eq(variables['Agent.Os'], 'Windows_NT'), 43 | in(variables['_SignType'], 'real', 'test') 44 | ), 45 | and( 46 | ${{ eq(parameters.enableMicrobuildForMacAndLinux, true) }}, 47 | ne(variables['Agent.Os'], 'Windows_NT'), 48 | eq(variables['_SignType'], 'real') 49 | ) 50 | )) 51 | -------------------------------------------------------------------------------- /eng/common/core-templates/steps/publish-build-artifacts.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: is1ESPipeline 3 | type: boolean 4 | default: false 5 | - name: args 6 | type: object 7 | default: {} 8 | steps: 9 | - ${{ if ne(parameters.is1ESPipeline, true) }}: 10 | - template: /eng/common/templates/steps/publish-build-artifacts.yml 11 | parameters: 12 | is1ESPipeline: ${{ parameters.is1ESPipeline }} 13 | ${{ each parameter in parameters.args }}: 14 | ${{ parameter.key }}: ${{ parameter.value }} 15 | - ${{ else }}: 16 | - template: /eng/common/templates-official/steps/publish-build-artifacts.yml 17 | parameters: 18 | is1ESPipeline: ${{ parameters.is1ESPipeline }} 19 | ${{ each parameter in parameters.args }}: 20 | ${{ parameter.key }}: ${{ parameter.value }} -------------------------------------------------------------------------------- /eng/common/core-templates/steps/publish-logs.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | StageLabel: '' 3 | JobLabel: '' 4 | CustomSensitiveDataList: '' 5 | # A default - in case value from eng/common/core-templates/post-build/common-variables.yml is not passed 6 | BinlogToolVersion: '1.0.11' 7 | is1ESPipeline: false 8 | 9 | steps: 10 | - task: Powershell@2 11 | displayName: Prepare Binlogs to Upload 12 | inputs: 13 | targetType: inline 14 | script: | 15 | New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ 16 | Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/ 17 | continueOnError: true 18 | condition: always() 19 | 20 | - task: PowerShell@2 21 | displayName: Redact Logs 22 | inputs: 23 | filePath: $(Build.SourcesDirectory)/eng/common/post-build/redact-logs.ps1 24 | # For now this needs to have explicit list of all sensitive data. Taken from eng/publishing/v3/publish.yml 25 | # Sensitive data can as well be added to $(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' 26 | # If the file exists - sensitive data for redaction will be sourced from it 27 | # (single entry per line, lines starting with '# ' are considered comments and skipped) 28 | arguments: -InputPath '$(Build.SourcesDirectory)/PostBuildLogs' 29 | -BinlogToolVersion ${{parameters.BinlogToolVersion}} 30 | -TokensFilePath '$(Build.SourcesDirectory)/eng/BinlogSecretsRedactionFile.txt' 31 | '$(publishing-dnceng-devdiv-code-r-build-re)' 32 | '$(MaestroAccessToken)' 33 | '$(dn-bot-all-orgs-artifact-feeds-rw)' 34 | '$(akams-client-id)' 35 | '$(microsoft-symbol-server-pat)' 36 | '$(symweb-symbol-server-pat)' 37 | '$(dnceng-symbol-server-pat)' 38 | '$(dn-bot-all-orgs-build-rw-code-rw)' 39 | '$(System.AccessToken)' 40 | ${{parameters.CustomSensitiveDataList}} 41 | continueOnError: true 42 | condition: always() 43 | 44 | - task: CopyFiles@2 45 | displayName: Gather post build logs 46 | inputs: 47 | SourceFolder: '$(Build.SourcesDirectory)/PostBuildLogs' 48 | Contents: '**' 49 | TargetFolder: '$(Build.ArtifactStagingDirectory)/PostBuildLogs' 50 | condition: always() 51 | 52 | - template: /eng/common/core-templates/steps/publish-build-artifacts.yml 53 | parameters: 54 | is1ESPipeline: ${{ parameters.is1ESPipeline }} 55 | args: 56 | displayName: Publish Logs 57 | pathToPublish: '$(Build.ArtifactStagingDirectory)/PostBuildLogs' 58 | publishLocation: Container 59 | artifactName: PostBuildLogs 60 | continueOnError: true 61 | condition: always() 62 | -------------------------------------------------------------------------------- /eng/common/core-templates/steps/publish-pipeline-artifacts.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: is1ESPipeline 3 | type: boolean 4 | default: false 5 | 6 | - name: args 7 | type: object 8 | default: {} 9 | 10 | steps: 11 | - ${{ if ne(parameters.is1ESPipeline, true) }}: 12 | - template: /eng/common/templates/steps/publish-pipeline-artifacts.yml 13 | parameters: 14 | ${{ each parameter in parameters }}: 15 | ${{ parameter.key }}: ${{ parameter.value }} 16 | - ${{ else }}: 17 | - template: /eng/common/templates-official/steps/publish-pipeline-artifacts.yml 18 | parameters: 19 | ${{ each parameter in parameters }}: 20 | ${{ parameter.key }}: ${{ parameter.value }} 21 | -------------------------------------------------------------------------------- /eng/common/core-templates/steps/retain-build.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | # Optional azure devops PAT with build execute permissions for the build's organization, 3 | # only needed if the build that should be retained ran on a different organization than 4 | # the pipeline where this template is executing from 5 | Token: '' 6 | # Optional BuildId to retain, defaults to the current running build 7 | BuildId: '' 8 | # Azure devops Organization URI for the build in the https://dev.azure.com/ format. 9 | # Defaults to the organization the current pipeline is running on 10 | AzdoOrgUri: '$(System.CollectionUri)' 11 | # Azure devops project for the build. Defaults to the project the current pipeline is running on 12 | AzdoProject: '$(System.TeamProject)' 13 | 14 | steps: 15 | - task: powershell@2 16 | inputs: 17 | targetType: 'filePath' 18 | filePath: eng/common/retain-build.ps1 19 | pwsh: true 20 | arguments: > 21 | -AzdoOrgUri: ${{parameters.AzdoOrgUri}} 22 | -AzdoProject ${{parameters.AzdoProject}} 23 | -Token ${{coalesce(parameters.Token, '$env:SYSTEM_ACCESSTOKEN') }} 24 | -BuildId ${{coalesce(parameters.BuildId, '$env:BUILD_ID')}} 25 | displayName: Enable permanent build retention 26 | env: 27 | SYSTEM_ACCESSTOKEN: $(System.AccessToken) 28 | BUILD_ID: $(Build.BuildId) -------------------------------------------------------------------------------- /eng/common/core-templates/steps/source-build.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | # This template adds arcade-powered source-build to CI. 3 | 4 | # This is a 'steps' template, and is intended for advanced scenarios where the existing build 5 | # infra has a careful build methodology that must be followed. For example, a repo 6 | # (dotnet/runtime) might choose to clone the GitHub repo only once and store it as a pipeline 7 | # artifact for all subsequent jobs to use, to reduce dependence on a strong network connection to 8 | # GitHub. Using this steps template leaves room for that infra to be included. 9 | 10 | # Defines the platform on which to run the steps. See 'eng/common/core-templates/job/source-build.yml' 11 | # for details. The entire object is described in the 'job' template for simplicity, even though 12 | # the usage of the properties on this object is split between the 'job' and 'steps' templates. 13 | platform: {} 14 | is1ESPipeline: false 15 | 16 | steps: 17 | # Build. Keep it self-contained for simple reusability. (No source-build-specific job variables.) 18 | - script: | 19 | set -x 20 | df -h 21 | 22 | # If building on the internal project, the internal storage variable may be available (usually only if needed) 23 | # In that case, add variables to allow the download of internal runtimes if the specified versions are not found 24 | # in the default public locations. 25 | internalRuntimeDownloadArgs= 26 | if [ '$(dotnetbuilds-internal-container-read-token-base64)' != '$''(dotnetbuilds-internal-container-read-token-base64)' ]; then 27 | internalRuntimeDownloadArgs='/p:DotNetRuntimeSourceFeed=https://ci.dot.net/internal /p:DotNetRuntimeSourceFeedKey=$(dotnetbuilds-internal-container-read-token-base64) --runtimesourcefeed https://ci.dot.net/internal --runtimesourcefeedkey $(dotnetbuilds-internal-container-read-token-base64)' 28 | fi 29 | 30 | buildConfig=Release 31 | # Check if AzDO substitutes in a build config from a variable, and use it if so. 32 | if [ '$(_BuildConfig)' != '$''(_BuildConfig)' ]; then 33 | buildConfig='$(_BuildConfig)' 34 | fi 35 | 36 | targetRidArgs= 37 | if [ '${{ parameters.platform.targetRID }}' != '' ]; then 38 | targetRidArgs='/p:TargetRid=${{ parameters.platform.targetRID }}' 39 | fi 40 | 41 | baseRidArgs= 42 | if [ '${{ parameters.platform.baseRID }}' != '' ]; then 43 | baseRidArgs='/p:BaseRid=${{ parameters.platform.baseRID }}' 44 | fi 45 | 46 | portableBuildArgs= 47 | if [ '${{ parameters.platform.portableBuild }}' != '' ]; then 48 | portableBuildArgs='/p:PortableBuild=${{ parameters.platform.portableBuild }}' 49 | fi 50 | 51 | ${{ coalesce(parameters.platform.buildScript, './build.sh') }} --ci \ 52 | --configuration $buildConfig \ 53 | --restore --build --pack -bl \ 54 | --source-build \ 55 | ${{ parameters.platform.buildArguments }} \ 56 | $internalRuntimeDownloadArgs \ 57 | $targetRidArgs \ 58 | $baseRidArgs \ 59 | $portableBuildArgs \ 60 | displayName: Build 61 | 62 | - template: /eng/common/core-templates/steps/publish-pipeline-artifacts.yml 63 | parameters: 64 | is1ESPipeline: ${{ parameters.is1ESPipeline }} 65 | args: 66 | displayName: Publish BuildLogs 67 | targetPath: artifacts/log/${{ coalesce(variables._BuildConfig, 'Release') }} 68 | artifactName: BuildLogs_SourceBuild_${{ parameters.platform.name }}_Attempt$(System.JobAttempt) 69 | continueOnError: true 70 | condition: succeededOrFailed() 71 | sbomEnabled: false # we don't need SBOM for logs 72 | -------------------------------------------------------------------------------- /eng/common/core-templates/steps/source-index-stage1-publish.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | sourceIndexUploadPackageVersion: 2.0.0-20250425.2 3 | sourceIndexProcessBinlogPackageVersion: 1.0.1-20250425.2 4 | sourceIndexPackageSource: https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json 5 | binlogPath: artifacts/log/Debug/Build.binlog 6 | 7 | steps: 8 | - task: UseDotNet@2 9 | displayName: "Source Index: Use .NET 8 SDK" 10 | inputs: 11 | packageType: sdk 12 | version: 8.0.x 13 | installationPath: $(Agent.TempDirectory)/dotnet 14 | workingDirectory: $(Agent.TempDirectory) 15 | 16 | - script: | 17 | $(Agent.TempDirectory)/dotnet/dotnet tool install BinLogToSln --version ${{parameters.sourceIndexProcessBinlogPackageVersion}} --add-source ${{parameters.SourceIndexPackageSource}} --tool-path $(Agent.TempDirectory)/.source-index/tools 18 | $(Agent.TempDirectory)/dotnet/dotnet tool install UploadIndexStage1 --version ${{parameters.sourceIndexUploadPackageVersion}} --add-source ${{parameters.SourceIndexPackageSource}} --tool-path $(Agent.TempDirectory)/.source-index/tools 19 | displayName: "Source Index: Download netsourceindex Tools" 20 | # Set working directory to temp directory so 'dotnet' doesn't try to use global.json and use the repo's sdk. 21 | workingDirectory: $(Agent.TempDirectory) 22 | 23 | - script: $(Agent.TempDirectory)/.source-index/tools/BinLogToSln -i ${{parameters.BinlogPath}} -r $(Build.SourcesDirectory) -n $(Build.Repository.Name) -o .source-index/stage1output 24 | displayName: "Source Index: Process Binlog into indexable sln" 25 | 26 | - ${{ if and(ne(parameters.runAsPublic, 'true'), ne(variables['System.TeamProject'], 'public'), notin(variables['Build.Reason'], 'PullRequest')) }}: 27 | - task: AzureCLI@2 28 | displayName: "Source Index: Upload Source Index stage1 artifacts to Azure" 29 | inputs: 30 | azureSubscription: 'SourceDotNet Stage1 Publish' 31 | addSpnToEnvironment: true 32 | scriptType: 'ps' 33 | scriptLocation: 'inlineScript' 34 | inlineScript: | 35 | $(Agent.TempDirectory)/.source-index/tools/UploadIndexStage1 -i .source-index/stage1output -n $(Build.Repository.Name) -s netsourceindexstage1 -b stage1 36 | -------------------------------------------------------------------------------- /eng/common/core-templates/variables/pool-providers.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | is1ESPipeline: false 3 | 4 | variables: 5 | - ${{ if eq(parameters.is1ESPipeline, 'true') }}: 6 | - template: /eng/common/templates-official/variables/pool-providers.yml 7 | - ${{ else }}: 8 | - template: /eng/common/templates/variables/pool-providers.yml -------------------------------------------------------------------------------- /eng/common/cross/arm/tizen/tizen.patch: -------------------------------------------------------------------------------- 1 | diff -u -r a/usr/lib/libc.so b/usr/lib/libc.so 2 | --- a/usr/lib/libc.so 2016-12-30 23:00:08.284951863 +0900 3 | +++ b/usr/lib/libc.so 2016-12-30 23:00:32.140951815 +0900 4 | @@ -2,4 +2,4 @@ 5 | Use the shared library, but some functions are only in 6 | the static library, so try that secondarily. */ 7 | OUTPUT_FORMAT(elf32-littlearm) 8 | -GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux-armhf.so.3 ) ) 9 | +GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux-armhf.so.3 ) ) 10 | -------------------------------------------------------------------------------- /eng/common/cross/arm64/tizen/tizen.patch: -------------------------------------------------------------------------------- 1 | diff -u -r a/usr/lib/libc.so b/usr/lib/libc.so 2 | --- a/usr/lib64/libc.so 2016-12-30 23:00:08.284951863 +0900 3 | +++ b/usr/lib64/libc.so 2016-12-30 23:00:32.140951815 +0900 4 | @@ -2,4 +2,4 @@ 5 | Use the shared library, but some functions are only in 6 | the static library, so try that secondarily. */ 7 | OUTPUT_FORMAT(elf64-littleaarch64) 8 | -GROUP ( /lib64/libc.so.6 /usr/lib64/libc_nonshared.a AS_NEEDED ( /lib64/ld-linux-aarch64.so.1 ) ) 9 | +GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux-aarch64.so.1 ) ) 10 | -------------------------------------------------------------------------------- /eng/common/cross/armel/tizen/tizen.patch: -------------------------------------------------------------------------------- 1 | diff -u -r a/usr/lib/libc.so b/usr/lib/libc.so 2 | --- a/usr/lib/libc.so 2016-12-30 23:00:08.284951863 +0900 3 | +++ b/usr/lib/libc.so 2016-12-30 23:00:32.140951815 +0900 4 | @@ -2,4 +2,4 @@ 5 | Use the shared library, but some functions are only in 6 | the static library, so try that secondarily. */ 7 | OUTPUT_FORMAT(elf32-littlearm) 8 | -GROUP ( /lib/libc.so.6 /usr/lib/libc_nonshared.a AS_NEEDED ( /lib/ld-linux.so.3 ) ) 9 | +GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux.so.3 ) ) 10 | -------------------------------------------------------------------------------- /eng/common/cross/riscv64/tizen/tizen.patch: -------------------------------------------------------------------------------- 1 | diff -u -r a/usr/lib/libc.so b/usr/lib/libc.so 2 | --- a/usr/lib64/libc.so 2016-12-30 23:00:08.284951863 +0900 3 | +++ b/usr/lib64/libc.so 2016-12-30 23:00:32.140951815 +0900 4 | @@ -2,4 +2,4 @@ 5 | Use the shared library, but some functions are only in 6 | the static library, so try that secondarily. */ 7 | OUTPUT_FORMAT(elf64-littleriscv) 8 | -GROUP ( /lib64/libc.so.6 /usr/lib64/libc_nonshared.a AS_NEEDED ( /lib64/ld-linux-riscv64-lp64d.so.1 ) ) 9 | +GROUP ( libc.so.6 libc_nonshared.a AS_NEEDED ( ld-linux-riscv64-lp64d.so.1 ) ) 10 | -------------------------------------------------------------------------------- /eng/common/cross/tizen-build-rootfs.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | ARCH=$1 5 | LINK_ARCH=$ARCH 6 | 7 | case "$ARCH" in 8 | arm) 9 | TIZEN_ARCH="armv7hl" 10 | ;; 11 | armel) 12 | TIZEN_ARCH="armv7l" 13 | LINK_ARCH="arm" 14 | ;; 15 | arm64) 16 | TIZEN_ARCH="aarch64" 17 | ;; 18 | x86) 19 | TIZEN_ARCH="i686" 20 | ;; 21 | x64) 22 | TIZEN_ARCH="x86_64" 23 | LINK_ARCH="x86" 24 | ;; 25 | riscv64) 26 | TIZEN_ARCH="riscv64" 27 | LINK_ARCH="riscv" 28 | ;; 29 | *) 30 | echo "Unsupported architecture for tizen: $ARCH" 31 | exit 1 32 | esac 33 | 34 | __CrossDir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) 35 | __TIZEN_CROSSDIR="$__CrossDir/${ARCH}/tizen" 36 | 37 | if [[ -z "$ROOTFS_DIR" ]]; then 38 | echo "ROOTFS_DIR is not defined." 39 | exit 1; 40 | fi 41 | 42 | TIZEN_TMP_DIR=$ROOTFS_DIR/tizen_tmp 43 | mkdir -p $TIZEN_TMP_DIR 44 | 45 | # Download files 46 | echo ">>Start downloading files" 47 | VERBOSE=1 $__CrossDir/tizen-fetch.sh $TIZEN_TMP_DIR $TIZEN_ARCH 48 | echo "<>Start constructing Tizen rootfs" 51 | TIZEN_RPM_FILES=`ls $TIZEN_TMP_DIR/*.rpm` 52 | cd $ROOTFS_DIR 53 | for f in $TIZEN_RPM_FILES; do 54 | rpm2cpio $f | cpio -idm --quiet 55 | done 56 | echo "<>Start configuring Tizen rootfs" 63 | ln -sfn asm-${LINK_ARCH} ./usr/include/asm 64 | patch -p1 < $__TIZEN_CROSSDIR/tizen.patch 65 | if [[ "$TIZEN_ARCH" == "riscv64" ]]; then 66 | echo "Fixing broken symlinks in $PWD" 67 | rm ./usr/lib64/libresolv.so 68 | ln -s ../../lib64/libresolv.so.2 ./usr/lib64/libresolv.so 69 | rm ./usr/lib64/libpthread.so 70 | ln -s ../../lib64/libpthread.so.0 ./usr/lib64/libpthread.so 71 | rm ./usr/lib64/libdl.so 72 | ln -s ../../lib64/libdl.so.2 ./usr/lib64/libdl.so 73 | rm ./usr/lib64/libutil.so 74 | ln -s ../../lib64/libutil.so.1 ./usr/lib64/libutil.so 75 | rm ./usr/lib64/libm.so 76 | ln -s ../../lib64/libm.so.6 ./usr/lib64/libm.so 77 | rm ./usr/lib64/librt.so 78 | ln -s ../../lib64/librt.so.1 ./usr/lib64/librt.so 79 | rm ./lib/ld-linux-riscv64-lp64d.so.1 80 | ln -s ../lib64/ld-linux-riscv64-lp64d.so.1 ./lib/ld-linux-riscv64-lp64d.so.1 81 | fi 82 | echo "< 0 ]]; do 9 | opt="$(echo "$1" | tr "[:upper:]" "[:lower:]")" 10 | case "$opt" in 11 | --darcversion) 12 | darcVersion=$2 13 | shift 14 | ;; 15 | --versionendpoint) 16 | versionEndpoint=$2 17 | shift 18 | ;; 19 | --verbosity) 20 | verbosity=$2 21 | shift 22 | ;; 23 | --toolpath) 24 | toolpath=$2 25 | shift 26 | ;; 27 | *) 28 | echo "Invalid argument: $1" 29 | usage 30 | exit 1 31 | ;; 32 | esac 33 | 34 | shift 35 | done 36 | 37 | # resolve $source until the file is no longer a symlink 38 | while [[ -h "$source" ]]; do 39 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 40 | source="$(readlink "$source")" 41 | # if $source was a relative symlink, we need to resolve it relative to the path where the 42 | # symlink file was located 43 | [[ $source != /* ]] && source="$scriptroot/$source" 44 | done 45 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 46 | 47 | . "$scriptroot/tools.sh" 48 | 49 | if [ -z "$darcVersion" ]; then 50 | darcVersion=$(curl -X GET "$versionEndpoint" -H "accept: text/plain") 51 | fi 52 | 53 | function InstallDarcCli { 54 | local darc_cli_package_name="microsoft.dotnet.darc" 55 | 56 | InitializeDotNetCli true 57 | local dotnet_root=$_InitializeDotNetCli 58 | 59 | if [ -z "$toolpath" ]; then 60 | local tool_list=$($dotnet_root/dotnet tool list -g) 61 | if [[ $tool_list = *$darc_cli_package_name* ]]; then 62 | echo $($dotnet_root/dotnet tool uninstall $darc_cli_package_name -g) 63 | fi 64 | else 65 | local tool_list=$($dotnet_root/dotnet tool list --tool-path "$toolpath") 66 | if [[ $tool_list = *$darc_cli_package_name* ]]; then 67 | echo $($dotnet_root/dotnet tool uninstall $darc_cli_package_name --tool-path "$toolpath") 68 | fi 69 | fi 70 | 71 | local arcadeServicesSource="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" 72 | 73 | echo "Installing Darc CLI version $darcVersion..." 74 | echo "You may need to restart your command shell if this is the first dotnet tool you have installed." 75 | if [ -z "$toolpath" ]; then 76 | echo $($dotnet_root/dotnet tool install $darc_cli_package_name --version $darcVersion --add-source "$arcadeServicesSource" -v $verbosity -g) 77 | else 78 | echo $($dotnet_root/dotnet tool install $darc_cli_package_name --version $darcVersion --add-source "$arcadeServicesSource" -v $verbosity --tool-path "$toolpath") 79 | fi 80 | } 81 | 82 | InstallDarcCli 83 | -------------------------------------------------------------------------------- /eng/common/dotnet-install.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0dotnet-install.ps1""" %*" -------------------------------------------------------------------------------- /eng/common/dotnet-install.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding(PositionalBinding=$false)] 2 | Param( 3 | [string] $verbosity = 'minimal', 4 | [string] $architecture = '', 5 | [string] $version = 'Latest', 6 | [string] $runtime = 'dotnet', 7 | [string] $RuntimeSourceFeed = '', 8 | [string] $RuntimeSourceFeedKey = '' 9 | ) 10 | 11 | . $PSScriptRoot\tools.ps1 12 | 13 | $dotnetRoot = Join-Path $RepoRoot '.dotnet' 14 | 15 | $installdir = $dotnetRoot 16 | try { 17 | if ($architecture -and $architecture.Trim() -eq 'x86') { 18 | $installdir = Join-Path $installdir 'x86' 19 | } 20 | InstallDotNet $installdir $version $architecture $runtime $true -RuntimeSourceFeed $RuntimeSourceFeed -RuntimeSourceFeedKey $RuntimeSourceFeedKey 21 | } 22 | catch { 23 | Write-Host $_.ScriptStackTrace 24 | Write-PipelineTelemetryError -Category 'InitializeToolset' -Message $_ 25 | ExitWithExitCode 1 26 | } 27 | 28 | ExitWithExitCode 0 29 | -------------------------------------------------------------------------------- /eng/common/dotnet-install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | # resolve $source until the file is no longer a symlink 5 | while [[ -h "$source" ]]; do 6 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 7 | source="$(readlink "$source")" 8 | # if $source was a relative symlink, we need to resolve it relative to the path where the 9 | # symlink file was located 10 | [[ $source != /* ]] && source="$scriptroot/$source" 11 | done 12 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 13 | 14 | . "$scriptroot/tools.sh" 15 | 16 | version='Latest' 17 | architecture='' 18 | runtime='dotnet' 19 | runtimeSourceFeed='' 20 | runtimeSourceFeedKey='' 21 | while [[ $# > 0 ]]; do 22 | opt="$(echo "$1" | tr "[:upper:]" "[:lower:]")" 23 | case "$opt" in 24 | -version|-v) 25 | shift 26 | version="$1" 27 | ;; 28 | -architecture|-a) 29 | shift 30 | architecture="$1" 31 | ;; 32 | -runtime|-r) 33 | shift 34 | runtime="$1" 35 | ;; 36 | -runtimesourcefeed) 37 | shift 38 | runtimeSourceFeed="$1" 39 | ;; 40 | -runtimesourcefeedkey) 41 | shift 42 | runtimeSourceFeedKey="$1" 43 | ;; 44 | *) 45 | Write-PipelineTelemetryError -Category 'Build' -Message "Invalid argument: $1" 46 | exit 1 47 | ;; 48 | esac 49 | shift 50 | done 51 | 52 | # Use uname to determine what the CPU is, see https://en.wikipedia.org/wiki/Uname#Examples 53 | cpuname=$(uname -m) 54 | case $cpuname in 55 | arm64|aarch64) 56 | buildarch=arm64 57 | if [ "$(getconf LONG_BIT)" -lt 64 ]; then 58 | # This is 32-bit OS running on 64-bit CPU (for example Raspberry Pi OS) 59 | buildarch=arm 60 | fi 61 | ;; 62 | loongarch64) 63 | buildarch=loongarch64 64 | ;; 65 | amd64|x86_64) 66 | buildarch=x64 67 | ;; 68 | armv*l) 69 | buildarch=arm 70 | ;; 71 | i[3-6]86) 72 | buildarch=x86 73 | ;; 74 | riscv64) 75 | buildarch=riscv64 76 | ;; 77 | *) 78 | echo "Unknown CPU $cpuname detected, treating it as x64" 79 | buildarch=x64 80 | ;; 81 | esac 82 | 83 | dotnetRoot="${repo_root}.dotnet" 84 | if [[ $architecture != "" ]] && [[ $architecture != $buildarch ]]; then 85 | dotnetRoot="$dotnetRoot/$architecture" 86 | fi 87 | 88 | InstallDotNet "$dotnetRoot" $version "$architecture" $runtime true $runtimeSourceFeed $runtimeSourceFeedKey || { 89 | local exit_code=$? 90 | Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "dotnet-install.sh failed (exit code '$exit_code')." >&2 91 | ExitWithExitCode $exit_code 92 | } 93 | 94 | ExitWithExitCode 0 95 | -------------------------------------------------------------------------------- /eng/common/enable-cross-org-publishing.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [string] $token 3 | ) 4 | 5 | 6 | . $PSScriptRoot\pipeline-logging-functions.ps1 7 | 8 | # Write-PipelineSetVariable will no-op if a variable named $ci is not defined 9 | # Since this script is only ever called in AzDO builds, just universally set it 10 | $ci = $true 11 | 12 | Write-PipelineSetVariable -Name 'VSS_NUGET_ACCESSTOKEN' -Value $token -IsMultiJobVariable $false 13 | Write-PipelineSetVariable -Name 'VSS_NUGET_URI_PREFIXES' -Value 'https://dnceng.pkgs.visualstudio.com/;https://pkgs.dev.azure.com/dnceng/;https://devdiv.pkgs.visualstudio.com/;https://pkgs.dev.azure.com/devdiv/' -IsMultiJobVariable $false 14 | -------------------------------------------------------------------------------- /eng/common/generate-sbom-prep.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [Parameter(Mandatory=$true)][string] $ManifestDirPath # Manifest directory where sbom will be placed 3 | ) 4 | 5 | . $PSScriptRoot\pipeline-logging-functions.ps1 6 | 7 | # Normally - we'd listen to the manifest path given, but 1ES templates will overwrite if this level gets uploaded directly 8 | # with their own overwriting ours. So we create it as a sub directory of the requested manifest path. 9 | $ArtifactName = "${env:SYSTEM_STAGENAME}_${env:AGENT_JOBNAME}_SBOM" 10 | $SafeArtifactName = $ArtifactName -replace '["/:<>\\|?@*"() ]', '_' 11 | $SbomGenerationDir = Join-Path $ManifestDirPath $SafeArtifactName 12 | 13 | Write-Host "Artifact name before : $ArtifactName" 14 | Write-Host "Artifact name after : $SafeArtifactName" 15 | 16 | Write-Host "Creating dir $ManifestDirPath" 17 | 18 | # create directory for sbom manifest to be placed 19 | if (!(Test-Path -path $SbomGenerationDir)) 20 | { 21 | New-Item -ItemType Directory -path $SbomGenerationDir 22 | Write-Host "Successfully created directory $SbomGenerationDir" 23 | } 24 | else{ 25 | Write-PipelineTelemetryError -category 'Build' "Unable to create sbom folder." 26 | } 27 | 28 | Write-Host "Updating artifact name" 29 | Write-Host "##vso[task.setvariable variable=ARTIFACT_NAME]$SafeArtifactName" 30 | -------------------------------------------------------------------------------- /eng/common/generate-sbom-prep.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | 5 | # resolve $SOURCE until the file is no longer a symlink 6 | while [[ -h $source ]]; do 7 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 8 | source="$(readlink "$source")" 9 | 10 | # if $source was a relative symlink, we need to resolve it relative to the path where the 11 | # symlink file was located 12 | [[ $source != /* ]] && source="$scriptroot/$source" 13 | done 14 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 15 | . $scriptroot/pipeline-logging-functions.sh 16 | 17 | 18 | # replace all special characters with _, some builds use special characters like : in Agent.Jobname, that is not a permissible name while uploading artifacts. 19 | artifact_name=$SYSTEM_STAGENAME"_"$AGENT_JOBNAME"_SBOM" 20 | safe_artifact_name="${artifact_name//["/:<>\\|?@*$" ]/_}" 21 | manifest_dir=$1 22 | 23 | # Normally - we'd listen to the manifest path given, but 1ES templates will overwrite if this level gets uploaded directly 24 | # with their own overwriting ours. So we create it as a sub directory of the requested manifest path. 25 | sbom_generation_dir="$manifest_dir/$safe_artifact_name" 26 | 27 | if [ ! -d "$sbom_generation_dir" ] ; then 28 | mkdir -p "$sbom_generation_dir" 29 | echo "Sbom directory created." $sbom_generation_dir 30 | else 31 | Write-PipelineTelemetryError -category 'Build' "Unable to create sbom folder." 32 | fi 33 | 34 | echo "Artifact name before : "$artifact_name 35 | echo "Artifact name after : "$safe_artifact_name 36 | export ARTIFACT_NAME=$safe_artifact_name 37 | echo "##vso[task.setvariable variable=ARTIFACT_NAME]$safe_artifact_name" 38 | 39 | exit 0 40 | -------------------------------------------------------------------------------- /eng/common/helixpublish.proj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | msbuild 6 | 7 | 8 | 9 | 10 | %(Identity) 11 | 12 | 13 | 14 | 15 | 16 | $(WorkItemDirectory) 17 | $(WorkItemCommand) 18 | $(WorkItemTimeout) 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /eng/common/init-tools-native.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | powershell -NoProfile -NoLogo -ExecutionPolicy ByPass -command "& """%~dp0init-tools-native.ps1""" %*" 3 | exit /b %ErrorLevel% -------------------------------------------------------------------------------- /eng/common/internal/Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | false 6 | false 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /eng/common/internal/NuGet.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /eng/common/internal/Tools.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | net472 6 | false 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /eng/common/loc/P22DotNetHtmlLocalization.lss: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 22 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /eng/common/msbuild.ps1: -------------------------------------------------------------------------------- 1 | [CmdletBinding(PositionalBinding=$false)] 2 | Param( 3 | [string] $verbosity = 'minimal', 4 | [bool] $warnAsError = $true, 5 | [bool] $nodeReuse = $true, 6 | [switch] $ci, 7 | [switch] $prepareMachine, 8 | [switch] $excludePrereleaseVS, 9 | [string] $msbuildEngine = $null, 10 | [Parameter(ValueFromRemainingArguments=$true)][String[]]$extraArgs 11 | ) 12 | 13 | . $PSScriptRoot\tools.ps1 14 | 15 | try { 16 | if ($ci) { 17 | $nodeReuse = $false 18 | } 19 | 20 | MSBuild @extraArgs 21 | } 22 | catch { 23 | Write-Host $_.ScriptStackTrace 24 | Write-PipelineTelemetryError -Category 'Build' -Message $_ 25 | ExitWithExitCode 1 26 | } 27 | 28 | ExitWithExitCode 0 -------------------------------------------------------------------------------- /eng/common/msbuild.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | 5 | # resolve $source until the file is no longer a symlink 6 | while [[ -h "$source" ]]; do 7 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 8 | source="$(readlink "$source")" 9 | # if $source was a relative symlink, we need to resolve it relative to the path where the 10 | # symlink file was located 11 | [[ $source != /* ]] && source="$scriptroot/$source" 12 | done 13 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 14 | 15 | verbosity='minimal' 16 | warn_as_error=true 17 | node_reuse=true 18 | prepare_machine=false 19 | extra_args='' 20 | 21 | while (($# > 0)); do 22 | lowerI="$(echo $1 | tr "[:upper:]" "[:lower:]")" 23 | case $lowerI in 24 | --verbosity) 25 | verbosity=$2 26 | shift 2 27 | ;; 28 | --warnaserror) 29 | warn_as_error=$2 30 | shift 2 31 | ;; 32 | --nodereuse) 33 | node_reuse=$2 34 | shift 2 35 | ;; 36 | --ci) 37 | ci=true 38 | shift 1 39 | ;; 40 | --preparemachine) 41 | prepare_machine=true 42 | shift 1 43 | ;; 44 | *) 45 | extra_args="$extra_args $1" 46 | shift 1 47 | ;; 48 | esac 49 | done 50 | 51 | . "$scriptroot/tools.sh" 52 | 53 | if [[ "$ci" == true ]]; then 54 | node_reuse=false 55 | fi 56 | 57 | MSBuild $extra_args 58 | ExitWithExitCode 0 59 | -------------------------------------------------------------------------------- /eng/common/native/init-os-and-arch.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Use uname to determine what the OS is. 4 | OSName=$(uname -s | tr '[:upper:]' '[:lower:]') 5 | 6 | if command -v getprop && getprop ro.product.system.model 2>&1 | grep -qi android; then 7 | OSName="android" 8 | fi 9 | 10 | case "$OSName" in 11 | freebsd|linux|netbsd|openbsd|sunos|android|haiku) 12 | os="$OSName" ;; 13 | darwin) 14 | os=osx ;; 15 | *) 16 | echo "Unsupported OS $OSName detected!" 17 | exit 1 ;; 18 | esac 19 | 20 | # On Solaris, `uname -m` is discouraged, see https://docs.oracle.com/cd/E36784_01/html/E36870/uname-1.html 21 | # and `uname -p` returns processor type (e.g. i386 on amd64). 22 | # The appropriate tool to determine CPU is isainfo(1) https://docs.oracle.com/cd/E36784_01/html/E36870/isainfo-1.html. 23 | if [ "$os" = "sunos" ]; then 24 | if uname -o 2>&1 | grep -q illumos; then 25 | os="illumos" 26 | else 27 | os="solaris" 28 | fi 29 | CPUName=$(isainfo -n) 30 | else 31 | # For the rest of the operating systems, use uname(1) to determine what the CPU is. 32 | CPUName=$(uname -m) 33 | fi 34 | 35 | case "$CPUName" in 36 | arm64|aarch64) 37 | arch=arm64 38 | if [ "$(getconf LONG_BIT)" -lt 64 ]; then 39 | # This is 32-bit OS running on 64-bit CPU (for example Raspberry Pi OS) 40 | arch=arm 41 | fi 42 | ;; 43 | 44 | loongarch64) 45 | arch=loongarch64 46 | ;; 47 | 48 | riscv64) 49 | arch=riscv64 50 | ;; 51 | 52 | amd64|x86_64) 53 | arch=x64 54 | ;; 55 | 56 | armv7l|armv8l) 57 | # shellcheck disable=SC1091 58 | if (NAME=""; . /etc/os-release; test "$NAME" = "Tizen"); then 59 | arch=armel 60 | else 61 | arch=arm 62 | fi 63 | ;; 64 | 65 | armv6l) 66 | arch=armv6 67 | ;; 68 | 69 | i[3-6]86) 70 | echo "Unsupported CPU $CPUName detected, build might not succeed!" 71 | arch=x86 72 | ;; 73 | 74 | s390x) 75 | arch=s390x 76 | ;; 77 | 78 | ppc64le) 79 | arch=ppc64le 80 | ;; 81 | *) 82 | echo "Unknown CPU $CPUName detected!" 83 | exit 1 84 | ;; 85 | esac 86 | -------------------------------------------------------------------------------- /eng/common/native/install-cmake-test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 5 | 6 | . $scriptroot/common-library.sh 7 | 8 | base_uri= 9 | install_path= 10 | version= 11 | clean=false 12 | force=false 13 | download_retries=5 14 | retry_wait_time_seconds=30 15 | 16 | while (($# > 0)); do 17 | lowerI="$(echo $1 | tr "[:upper:]" "[:lower:]")" 18 | case $lowerI in 19 | --baseuri) 20 | base_uri=$2 21 | shift 2 22 | ;; 23 | --installpath) 24 | install_path=$2 25 | shift 2 26 | ;; 27 | --version) 28 | version=$2 29 | shift 2 30 | ;; 31 | --clean) 32 | clean=true 33 | shift 1 34 | ;; 35 | --force) 36 | force=true 37 | shift 1 38 | ;; 39 | --downloadretries) 40 | download_retries=$2 41 | shift 2 42 | ;; 43 | --retrywaittimeseconds) 44 | retry_wait_time_seconds=$2 45 | shift 2 46 | ;; 47 | --help) 48 | echo "Common settings:" 49 | echo " --baseuri Base file directory or Url wrom which to acquire tool archives" 50 | echo " --installpath Base directory to install native tool to" 51 | echo " --clean Don't install the tool, just clean up the current install of the tool" 52 | echo " --force Force install of tools even if they previously exist" 53 | echo " --help Print help and exit" 54 | echo "" 55 | echo "Advanced settings:" 56 | echo " --downloadretries Total number of retry attempts" 57 | echo " --retrywaittimeseconds Wait time between retry attempts in seconds" 58 | echo "" 59 | exit 0 60 | ;; 61 | esac 62 | done 63 | 64 | tool_name="cmake-test" 65 | tool_os=$(GetCurrentOS) 66 | tool_folder="$(echo $tool_os | tr "[:upper:]" "[:lower:]")" 67 | tool_arch="x86_64" 68 | tool_name_moniker="$tool_name-$version-$tool_os-$tool_arch" 69 | tool_install_directory="$install_path/$tool_name/$version" 70 | tool_file_path="$tool_install_directory/$tool_name_moniker/bin/$tool_name" 71 | shim_path="$install_path/$tool_name.sh" 72 | uri="${base_uri}/$tool_folder/$tool_name/$tool_name_moniker.tar.gz" 73 | 74 | # Clean up tool and installers 75 | if [[ $clean = true ]]; then 76 | echo "Cleaning $tool_install_directory" 77 | if [[ -d $tool_install_directory ]]; then 78 | rm -rf $tool_install_directory 79 | fi 80 | 81 | echo "Cleaning $shim_path" 82 | if [[ -f $shim_path ]]; then 83 | rm -rf $shim_path 84 | fi 85 | 86 | tool_temp_path=$(GetTempPathFileName $uri) 87 | echo "Cleaning $tool_temp_path" 88 | if [[ -f $tool_temp_path ]]; then 89 | rm -rf $tool_temp_path 90 | fi 91 | 92 | exit 0 93 | fi 94 | 95 | # Install tool 96 | if [[ -f $tool_file_path ]] && [[ $force = false ]]; then 97 | echo "$tool_name ($version) already exists, skipping install" 98 | exit 0 99 | fi 100 | 101 | DownloadAndExtract $uri $tool_install_directory $force $download_retries $retry_wait_time_seconds 102 | 103 | if [[ $? != 0 ]]; then 104 | Write-PipelineTelemetryError -category 'NativeToolsBootstrap' 'Installation failed' 105 | exit 1 106 | fi 107 | 108 | # Generate Shim 109 | # Always rewrite shims so that we are referencing the expected version 110 | NewScriptShim $shim_path $tool_file_path true 111 | 112 | if [[ $? != 0 ]]; then 113 | Write-PipelineTelemetryError -category 'NativeToolsBootstrap' 'Shim generation failed' 114 | exit 1 115 | fi 116 | 117 | exit 0 118 | -------------------------------------------------------------------------------- /eng/common/native/install-cmake.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source="${BASH_SOURCE[0]}" 4 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 5 | 6 | . $scriptroot/common-library.sh 7 | 8 | base_uri= 9 | install_path= 10 | version= 11 | clean=false 12 | force=false 13 | download_retries=5 14 | retry_wait_time_seconds=30 15 | 16 | while (($# > 0)); do 17 | lowerI="$(echo $1 | tr "[:upper:]" "[:lower:]")" 18 | case $lowerI in 19 | --baseuri) 20 | base_uri=$2 21 | shift 2 22 | ;; 23 | --installpath) 24 | install_path=$2 25 | shift 2 26 | ;; 27 | --version) 28 | version=$2 29 | shift 2 30 | ;; 31 | --clean) 32 | clean=true 33 | shift 1 34 | ;; 35 | --force) 36 | force=true 37 | shift 1 38 | ;; 39 | --downloadretries) 40 | download_retries=$2 41 | shift 2 42 | ;; 43 | --retrywaittimeseconds) 44 | retry_wait_time_seconds=$2 45 | shift 2 46 | ;; 47 | --help) 48 | echo "Common settings:" 49 | echo " --baseuri Base file directory or Url wrom which to acquire tool archives" 50 | echo " --installpath Base directory to install native tool to" 51 | echo " --clean Don't install the tool, just clean up the current install of the tool" 52 | echo " --force Force install of tools even if they previously exist" 53 | echo " --help Print help and exit" 54 | echo "" 55 | echo "Advanced settings:" 56 | echo " --downloadretries Total number of retry attempts" 57 | echo " --retrywaittimeseconds Wait time between retry attempts in seconds" 58 | echo "" 59 | exit 0 60 | ;; 61 | esac 62 | done 63 | 64 | tool_name="cmake" 65 | tool_os=$(GetCurrentOS) 66 | tool_folder="$(echo $tool_os | tr "[:upper:]" "[:lower:]")" 67 | tool_arch="x86_64" 68 | tool_name_moniker="$tool_name-$version-$tool_os-$tool_arch" 69 | tool_install_directory="$install_path/$tool_name/$version" 70 | tool_file_path="$tool_install_directory/$tool_name_moniker/bin/$tool_name" 71 | shim_path="$install_path/$tool_name.sh" 72 | uri="${base_uri}/$tool_folder/$tool_name/$tool_name_moniker.tar.gz" 73 | 74 | # Clean up tool and installers 75 | if [[ $clean = true ]]; then 76 | echo "Cleaning $tool_install_directory" 77 | if [[ -d $tool_install_directory ]]; then 78 | rm -rf $tool_install_directory 79 | fi 80 | 81 | echo "Cleaning $shim_path" 82 | if [[ -f $shim_path ]]; then 83 | rm -rf $shim_path 84 | fi 85 | 86 | tool_temp_path=$(GetTempPathFileName $uri) 87 | echo "Cleaning $tool_temp_path" 88 | if [[ -f $tool_temp_path ]]; then 89 | rm -rf $tool_temp_path 90 | fi 91 | 92 | exit 0 93 | fi 94 | 95 | # Install tool 96 | if [[ -f $tool_file_path ]] && [[ $force = false ]]; then 97 | echo "$tool_name ($version) already exists, skipping install" 98 | exit 0 99 | fi 100 | 101 | DownloadAndExtract $uri $tool_install_directory $force $download_retries $retry_wait_time_seconds 102 | 103 | if [[ $? != 0 ]]; then 104 | Write-PipelineTelemetryError -category 'NativeToolsBootstrap' 'Installation failed' 105 | exit 1 106 | fi 107 | 108 | # Generate Shim 109 | # Always rewrite shims so that we are referencing the expected version 110 | NewScriptShim $shim_path $tool_file_path true 111 | 112 | if [[ $? != 0 ]]; then 113 | Write-PipelineTelemetryError -category 'NativeToolsBootstrap' 'Shim generation failed' 114 | exit 1 115 | fi 116 | 117 | exit 0 118 | -------------------------------------------------------------------------------- /eng/common/native/install-dependencies.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | # This is a simple script primarily used for CI to install necessary dependencies 6 | # 7 | # Usage: 8 | # 9 | # ./install-dependencies.sh 10 | 11 | os="$(echo "$1" | tr "[:upper:]" "[:lower:]")" 12 | 13 | if [ -z "$os" ]; then 14 | . "$(dirname "$0")"/init-os-and-arch.sh 15 | fi 16 | 17 | case "$os" in 18 | linux) 19 | if [ -e /etc/os-release ]; then 20 | . /etc/os-release 21 | fi 22 | 23 | if [ "$ID" = "debian" ] || [ "$ID_LIKE" = "debian" ]; then 24 | apt update 25 | 26 | apt install -y build-essential gettext locales cmake llvm clang lld lldb liblldb-dev libunwind8-dev libicu-dev liblttng-ust-dev \ 27 | libssl-dev libkrb5-dev pigz cpio 28 | 29 | localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 30 | elif [ "$ID" = "fedora" ] || [ "$ID" = "rhel" ] || [ "$ID" = "azurelinux" ]; then 31 | pkg_mgr="$(command -v tdnf 2>/dev/null || command -v dnf)" 32 | $pkg_mgr install -y cmake llvm lld lldb clang python curl libicu-devel openssl-devel krb5-devel lttng-ust-devel pigz cpio 33 | elif [ "$ID" = "alpine" ]; then 34 | apk add build-base cmake bash curl clang llvm-dev lld lldb krb5-dev lttng-ust-dev icu-dev openssl-dev pigz cpio 35 | else 36 | echo "Unsupported distro. distro: $ID" 37 | exit 1 38 | fi 39 | ;; 40 | 41 | osx|maccatalyst|ios|iossimulator|tvos|tvossimulator) 42 | echo "Installed xcode version: $(xcode-select -p)" 43 | 44 | export HOMEBREW_NO_INSTALL_CLEANUP=1 45 | export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 46 | # Skip brew update for now, see https://github.com/actions/setup-python/issues/577 47 | # brew update --preinstall 48 | brew bundle --no-upgrade --file=- < Name of Arcade task (name of a project in SdkTasks directory of the Arcade SDK package)" 6 | echo " --restore Restore dependencies" 7 | echo " --verbosity Msbuild verbosity: q[uiet], m[inimal], n[ormal], d[etailed], and diag[nostic]" 8 | echo " --help Print help and exit" 9 | echo "" 10 | 11 | echo "Advanced settings:" 12 | echo " --excludeCIBinarylog Don't output binary log (short: -nobl)" 13 | echo "" 14 | echo "Command line arguments not listed above are passed thru to msbuild." 15 | } 16 | 17 | source="${BASH_SOURCE[0]}" 18 | 19 | # resolve $source until the file is no longer a symlink 20 | while [[ -h "$source" ]]; do 21 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 22 | source="$(readlink "$source")" 23 | # if $source was a relative symlink, we need to resolve it relative to the path where the 24 | # symlink file was located 25 | [[ $source != /* ]] && source="$scriptroot/$source" 26 | done 27 | scriptroot="$( cd -P "$( dirname "$source" )" && pwd )" 28 | 29 | Build() { 30 | local target=$1 31 | local log_suffix="" 32 | [[ "$target" != "Execute" ]] && log_suffix=".$target" 33 | local log="$log_dir/$task$log_suffix.binlog" 34 | local binaryLogArg="" 35 | [[ $binary_log == true ]] && binaryLogArg="/bl:$log" 36 | local output_path="$toolset_dir/$task/" 37 | 38 | MSBuild "$taskProject" \ 39 | $binaryLogArg \ 40 | /t:"$target" \ 41 | /p:Configuration="$configuration" \ 42 | /p:RepoRoot="$repo_root" \ 43 | /p:BaseIntermediateOutputPath="$output_path" \ 44 | /v:"$verbosity" \ 45 | $properties 46 | } 47 | 48 | binary_log=true 49 | configuration="Debug" 50 | verbosity="minimal" 51 | exclude_ci_binary_log=false 52 | restore=false 53 | help=false 54 | properties='' 55 | 56 | while (($# > 0)); do 57 | lowerI="$(echo $1 | tr "[:upper:]" "[:lower:]")" 58 | case $lowerI in 59 | --task) 60 | task=$2 61 | shift 2 62 | ;; 63 | --restore) 64 | restore=true 65 | shift 1 66 | ;; 67 | --verbosity) 68 | verbosity=$2 69 | shift 2 70 | ;; 71 | --excludecibinarylog|--nobl) 72 | binary_log=false 73 | exclude_ci_binary_log=true 74 | shift 1 75 | ;; 76 | --help) 77 | help=true 78 | shift 1 79 | ;; 80 | *) 81 | properties="$properties $1" 82 | shift 1 83 | ;; 84 | esac 85 | done 86 | 87 | ci=true 88 | warnAsError=true 89 | 90 | if $help; then 91 | show_usage 92 | exit 0 93 | fi 94 | 95 | . "$scriptroot/tools.sh" 96 | InitializeToolset 97 | 98 | if [[ -z "$task" ]]; then 99 | Write-PipelineTelemetryError -Category 'Task' -Name 'MissingTask' -Message "Missing required parameter '-task '" 100 | ExitWithExitCode 1 101 | fi 102 | 103 | taskProject=$(GetSdkTaskProject "$task") 104 | if [[ ! -e "$taskProject" ]]; then 105 | Write-PipelineTelemetryError -Category 'Task' -Name 'UnknownTask' -Message "Unknown task: $task" 106 | ExitWithExitCode 1 107 | fi 108 | 109 | if $restore; then 110 | Build "Restore" 111 | fi 112 | 113 | Build "Execute" 114 | 115 | 116 | ExitWithExitCode 0 117 | -------------------------------------------------------------------------------- /eng/common/sdl/NuGet.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /eng/common/sdl/extract-artifact-archives.ps1: -------------------------------------------------------------------------------- 1 | # This script looks for each archive file in a directory and extracts it into the target directory. 2 | # For example, the file "$InputPath/bin.tar.gz" extracts to "$ExtractPath/bin.tar.gz.extracted/**". 3 | # Uses the "tar" utility added to Windows 10 / Windows 2019 that supports tar.gz and zip. 4 | param( 5 | # Full path to directory where archives are stored. 6 | [Parameter(Mandatory=$true)][string] $InputPath, 7 | # Full path to directory to extract archives into. May be the same as $InputPath. 8 | [Parameter(Mandatory=$true)][string] $ExtractPath 9 | ) 10 | 11 | $ErrorActionPreference = 'Stop' 12 | Set-StrictMode -Version 2.0 13 | 14 | $disableConfigureToolsetImport = $true 15 | 16 | try { 17 | # `tools.ps1` checks $ci to perform some actions. Since the SDL 18 | # scripts don't necessarily execute in the same agent that run the 19 | # build.ps1/sh script this variable isn't automatically set. 20 | $ci = $true 21 | . $PSScriptRoot\..\tools.ps1 22 | 23 | Measure-Command { 24 | $jobs = @() 25 | 26 | # Find archive files for non-Windows and Windows builds. 27 | $archiveFiles = @( 28 | Get-ChildItem (Join-Path $InputPath "*.tar.gz") 29 | Get-ChildItem (Join-Path $InputPath "*.zip") 30 | ) 31 | 32 | foreach ($targzFile in $archiveFiles) { 33 | $jobs += Start-Job -ScriptBlock { 34 | $file = $using:targzFile 35 | $fileName = [System.IO.Path]::GetFileName($file) 36 | $extractDir = Join-Path $using:ExtractPath "$fileName.extracted" 37 | 38 | New-Item $extractDir -ItemType Directory -Force | Out-Null 39 | 40 | Write-Host "Extracting '$file' to '$extractDir'..." 41 | 42 | # Pipe errors to stdout to prevent PowerShell detecting them and quitting the job early. 43 | # This type of quit skips the catch, so we wouldn't be able to tell which file triggered the 44 | # error. Save output so it can be stored in the exception string along with context. 45 | $output = tar -xf $file -C $extractDir 2>&1 46 | # Handle NZEC manually rather than using Exit-IfNZEC: we are in a background job, so we 47 | # don't have access to the outer scope. 48 | if ($LASTEXITCODE -ne 0) { 49 | throw "Error extracting '$file': non-zero exit code ($LASTEXITCODE). Output: '$output'" 50 | } 51 | 52 | Write-Host "Extracted to $extractDir" 53 | } 54 | } 55 | 56 | Receive-Job $jobs -Wait 57 | } 58 | } 59 | catch { 60 | Write-Host $_ 61 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ 62 | ExitWithExitCode 1 63 | } 64 | -------------------------------------------------------------------------------- /eng/common/sdl/extract-artifact-packages.ps1: -------------------------------------------------------------------------------- 1 | param( 2 | [Parameter(Mandatory=$true)][string] $InputPath, # Full path to directory where artifact packages are stored 3 | [Parameter(Mandatory=$true)][string] $ExtractPath # Full path to directory where the packages will be extracted 4 | ) 5 | 6 | $ErrorActionPreference = 'Stop' 7 | Set-StrictMode -Version 2.0 8 | 9 | $disableConfigureToolsetImport = $true 10 | 11 | function ExtractArtifacts { 12 | if (!(Test-Path $InputPath)) { 13 | Write-Host "Input Path does not exist: $InputPath" 14 | ExitWithExitCode 0 15 | } 16 | $Jobs = @() 17 | Get-ChildItem "$InputPath\*.nupkg" | 18 | ForEach-Object { 19 | $Jobs += Start-Job -ScriptBlock $ExtractPackage -ArgumentList $_.FullName 20 | } 21 | 22 | foreach ($Job in $Jobs) { 23 | Wait-Job -Id $Job.Id | Receive-Job 24 | } 25 | } 26 | 27 | try { 28 | # `tools.ps1` checks $ci to perform some actions. Since the SDL 29 | # scripts don't necessarily execute in the same agent that run the 30 | # build.ps1/sh script this variable isn't automatically set. 31 | $ci = $true 32 | . $PSScriptRoot\..\tools.ps1 33 | 34 | $ExtractPackage = { 35 | param( 36 | [string] $PackagePath # Full path to a NuGet package 37 | ) 38 | 39 | if (!(Test-Path $PackagePath)) { 40 | Write-PipelineTelemetryError -Category 'Build' -Message "Input file does not exist: $PackagePath" 41 | ExitWithExitCode 1 42 | } 43 | 44 | $RelevantExtensions = @('.dll', '.exe', '.pdb') 45 | Write-Host -NoNewLine 'Extracting ' ([System.IO.Path]::GetFileName($PackagePath)) '...' 46 | 47 | $PackageId = [System.IO.Path]::GetFileNameWithoutExtension($PackagePath) 48 | $ExtractPath = Join-Path -Path $using:ExtractPath -ChildPath $PackageId 49 | 50 | Add-Type -AssemblyName System.IO.Compression.FileSystem 51 | 52 | [System.IO.Directory]::CreateDirectory($ExtractPath); 53 | 54 | try { 55 | $zip = [System.IO.Compression.ZipFile]::OpenRead($PackagePath) 56 | 57 | $zip.Entries | 58 | Where-Object {$RelevantExtensions -contains [System.IO.Path]::GetExtension($_.Name)} | 59 | ForEach-Object { 60 | $TargetPath = Join-Path -Path $ExtractPath -ChildPath (Split-Path -Path $_.FullName) 61 | [System.IO.Directory]::CreateDirectory($TargetPath); 62 | 63 | $TargetFile = Join-Path -Path $ExtractPath -ChildPath $_.FullName 64 | [System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, $TargetFile) 65 | } 66 | } 67 | catch { 68 | Write-Host $_ 69 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ 70 | ExitWithExitCode 1 71 | } 72 | finally { 73 | $zip.Dispose() 74 | } 75 | } 76 | Measure-Command { ExtractArtifacts } 77 | } 78 | catch { 79 | Write-Host $_ 80 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ 81 | ExitWithExitCode 1 82 | } 83 | -------------------------------------------------------------------------------- /eng/common/sdl/init-sdl.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $GuardianCliLocation, 3 | [string] $Repository, 4 | [string] $BranchName='master', 5 | [string] $WorkingDirectory, 6 | [string] $AzureDevOpsAccessToken, 7 | [string] $GuardianLoggerLevel='Standard' 8 | ) 9 | 10 | $ErrorActionPreference = 'Stop' 11 | Set-StrictMode -Version 2.0 12 | $disableConfigureToolsetImport = $true 13 | $global:LASTEXITCODE = 0 14 | 15 | # `tools.ps1` checks $ci to perform some actions. Since the SDL 16 | # scripts don't necessarily execute in the same agent that run the 17 | # build.ps1/sh script this variable isn't automatically set. 18 | $ci = $true 19 | . $PSScriptRoot\..\tools.ps1 20 | 21 | # Don't display the console progress UI - it's a huge perf hit 22 | $ProgressPreference = 'SilentlyContinue' 23 | 24 | # Construct basic auth from AzDO access token; construct URI to the repository's gdn folder stored in that repository; construct location of zip file 25 | $encodedPat = [Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$AzureDevOpsAccessToken")) 26 | $escapedRepository = [Uri]::EscapeDataString("/$Repository/$BranchName/.gdn") 27 | $uri = "https://dev.azure.com/dnceng/internal/_apis/git/repositories/sdl-tool-cfg/Items?path=$escapedRepository&versionDescriptor[versionOptions]=0&`$format=zip&api-version=5.0" 28 | $zipFile = "$WorkingDirectory/gdn.zip" 29 | 30 | Add-Type -AssemblyName System.IO.Compression.FileSystem 31 | $gdnFolder = (Join-Path $WorkingDirectory '.gdn') 32 | 33 | try { 34 | # if the folder does not exist, we'll do a guardian init and push it to the remote repository 35 | Write-Host 'Initializing Guardian...' 36 | Write-Host "$GuardianCliLocation init --working-directory $WorkingDirectory --logger-level $GuardianLoggerLevel" 37 | & $GuardianCliLocation init --working-directory $WorkingDirectory --logger-level $GuardianLoggerLevel 38 | if ($LASTEXITCODE -ne 0) { 39 | Write-PipelineTelemetryError -Force -Category 'Build' -Message "Guardian init failed with exit code $LASTEXITCODE." 40 | ExitWithExitCode $LASTEXITCODE 41 | } 42 | # We create the mainbaseline so it can be edited later 43 | Write-Host "$GuardianCliLocation baseline --working-directory $WorkingDirectory --name mainbaseline" 44 | & $GuardianCliLocation baseline --working-directory $WorkingDirectory --name mainbaseline 45 | if ($LASTEXITCODE -ne 0) { 46 | Write-PipelineTelemetryError -Force -Category 'Build' -Message "Guardian baseline failed with exit code $LASTEXITCODE." 47 | ExitWithExitCode $LASTEXITCODE 48 | } 49 | ExitWithExitCode 0 50 | } 51 | catch { 52 | Write-Host $_.ScriptStackTrace 53 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ 54 | ExitWithExitCode 1 55 | } 56 | -------------------------------------------------------------------------------- /eng/common/sdl/packages.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /eng/common/sdl/run-sdl.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [string] $GuardianCliLocation, 3 | [string] $WorkingDirectory, 4 | [string] $GdnFolder, 5 | [string] $UpdateBaseline, 6 | [string] $GuardianLoggerLevel='Standard' 7 | ) 8 | 9 | $ErrorActionPreference = 'Stop' 10 | Set-StrictMode -Version 2.0 11 | $disableConfigureToolsetImport = $true 12 | $global:LASTEXITCODE = 0 13 | 14 | try { 15 | # `tools.ps1` checks $ci to perform some actions. Since the SDL 16 | # scripts don't necessarily execute in the same agent that run the 17 | # build.ps1/sh script this variable isn't automatically set. 18 | $ci = $true 19 | . $PSScriptRoot\..\tools.ps1 20 | 21 | # We store config files in the r directory of .gdn 22 | $gdnConfigPath = Join-Path $GdnFolder 'r' 23 | $ValidPath = Test-Path $GuardianCliLocation 24 | 25 | if ($ValidPath -eq $False) 26 | { 27 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "Invalid Guardian CLI Location." 28 | ExitWithExitCode 1 29 | } 30 | 31 | $gdnConfigFiles = Get-ChildItem $gdnConfigPath -Recurse -Include '*.gdnconfig' 32 | Write-Host "Discovered Guardian config files:" 33 | $gdnConfigFiles | Out-String | Write-Host 34 | 35 | Exec-BlockVerbosely { 36 | & $GuardianCliLocation run ` 37 | --working-directory $WorkingDirectory ` 38 | --baseline mainbaseline ` 39 | --update-baseline $UpdateBaseline ` 40 | --logger-level $GuardianLoggerLevel ` 41 | --config @gdnConfigFiles 42 | Exit-IfNZEC "Sdl" 43 | } 44 | } 45 | catch { 46 | Write-Host $_.ScriptStackTrace 47 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ 48 | ExitWithExitCode 1 49 | } 50 | -------------------------------------------------------------------------------- /eng/common/sdl/sdl.ps1: -------------------------------------------------------------------------------- 1 | 2 | function Install-Gdn { 3 | param( 4 | [Parameter(Mandatory=$true)] 5 | [string]$Path, 6 | 7 | # If omitted, install the latest version of Guardian, otherwise install that specific version. 8 | [string]$Version 9 | ) 10 | 11 | $ErrorActionPreference = 'Stop' 12 | Set-StrictMode -Version 2.0 13 | $disableConfigureToolsetImport = $true 14 | $global:LASTEXITCODE = 0 15 | 16 | # `tools.ps1` checks $ci to perform some actions. Since the SDL 17 | # scripts don't necessarily execute in the same agent that run the 18 | # build.ps1/sh script this variable isn't automatically set. 19 | $ci = $true 20 | . $PSScriptRoot\..\tools.ps1 21 | 22 | $argumentList = @("install", "Microsoft.Guardian.Cli", "-Source https://securitytools.pkgs.visualstudio.com/_packaging/Guardian/nuget/v3/index.json", "-OutputDirectory $Path", "-NonInteractive", "-NoCache") 23 | 24 | if ($Version) { 25 | $argumentList += "-Version $Version" 26 | } 27 | 28 | Start-Process nuget -Verbose -ArgumentList $argumentList -NoNewWindow -Wait 29 | 30 | $gdnCliPath = Get-ChildItem -Filter guardian.cmd -Recurse -Path $Path 31 | 32 | if (!$gdnCliPath) 33 | { 34 | Write-PipelineTelemetryError -Category 'Sdl' -Message 'Failure installing Guardian' 35 | } 36 | 37 | return $gdnCliPath.FullName 38 | } -------------------------------------------------------------------------------- /eng/common/sdl/trim-assets-version.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Install and run the 'Microsoft.DotNet.VersionTools.Cli' tool with the 'trim-artifacts-version' command to trim the version from the NuGet assets file name. 4 | 5 | .PARAMETER InputPath 6 | Full path to directory where artifact packages are stored 7 | 8 | .PARAMETER Recursive 9 | Search for NuGet packages recursively 10 | 11 | #> 12 | 13 | Param( 14 | [string] $InputPath, 15 | [bool] $Recursive = $true 16 | ) 17 | 18 | $CliToolName = "Microsoft.DotNet.VersionTools.Cli" 19 | 20 | function Install-VersionTools-Cli { 21 | param( 22 | [Parameter(Mandatory=$true)][string]$Version 23 | ) 24 | 25 | Write-Host "Installing the package '$CliToolName' with a version of '$version' ..." 26 | $feed = "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" 27 | 28 | $argumentList = @("tool", "install", "--local", "$CliToolName", "--add-source $feed", "--no-cache", "--version $Version", "--create-manifest-if-needed") 29 | Start-Process "$dotnet" -Verbose -ArgumentList $argumentList -NoNewWindow -Wait 30 | } 31 | 32 | # ------------------------------------------------------------------- 33 | 34 | if (!(Test-Path $InputPath)) { 35 | Write-Host "Input Path '$InputPath' does not exist" 36 | ExitWithExitCode 1 37 | } 38 | 39 | $ErrorActionPreference = 'Stop' 40 | Set-StrictMode -Version 2.0 41 | 42 | $disableConfigureToolsetImport = $true 43 | $global:LASTEXITCODE = 0 44 | 45 | # `tools.ps1` checks $ci to perform some actions. Since the SDL 46 | # scripts don't necessarily execute in the same agent that run the 47 | # build.ps1/sh script this variable isn't automatically set. 48 | $ci = $true 49 | . $PSScriptRoot\..\tools.ps1 50 | 51 | try { 52 | $dotnetRoot = InitializeDotNetCli -install:$true 53 | $dotnet = "$dotnetRoot\dotnet.exe" 54 | 55 | $toolsetVersion = Read-ArcadeSdkVersion 56 | Install-VersionTools-Cli -Version $toolsetVersion 57 | 58 | $cliToolFound = (& "$dotnet" tool list --local | Where-Object {$_.Split(' ')[0] -eq $CliToolName}) 59 | if ($null -eq $cliToolFound) { 60 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message "The '$CliToolName' tool is not installed." 61 | ExitWithExitCode 1 62 | } 63 | 64 | Exec-BlockVerbosely { 65 | & "$dotnet" $CliToolName trim-assets-version ` 66 | --assets-path $InputPath ` 67 | --recursive $Recursive 68 | Exit-IfNZEC "Sdl" 69 | } 70 | } 71 | catch { 72 | Write-Host $_ 73 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_ 74 | ExitWithExitCode 1 75 | } 76 | -------------------------------------------------------------------------------- /eng/common/templates-official/job/onelocbuild.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - template: /eng/common/core-templates/job/onelocbuild.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates-official/job/publish-build-assets.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - template: /eng/common/core-templates/job/publish-build-assets.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates-official/job/source-build.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - template: /eng/common/core-templates/job/source-build.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates-official/job/source-index-stage1.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - template: /eng/common/core-templates/job/source-index-stage1.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates-official/jobs/codeql-build.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - template: /eng/common/core-templates/jobs/codeql-build.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates-official/jobs/jobs.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - template: /eng/common/core-templates/jobs/jobs.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates-official/jobs/source-build.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - template: /eng/common/core-templates/jobs/source-build.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} -------------------------------------------------------------------------------- /eng/common/templates-official/post-build/common-variables.yml: -------------------------------------------------------------------------------- 1 | variables: 2 | - template: /eng/common/core-templates/post-build/common-variables.yml 3 | parameters: 4 | # Specifies whether to use 1ES 5 | is1ESPipeline: true 6 | 7 | ${{ each parameter in parameters }}: 8 | ${{ parameter.key }}: ${{ parameter.value }} -------------------------------------------------------------------------------- /eng/common/templates-official/post-build/post-build.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - template: /eng/common/core-templates/post-build/post-build.yml 3 | parameters: 4 | # Specifies whether to use 1ES 5 | is1ESPipeline: true 6 | 7 | ${{ each parameter in parameters }}: 8 | ${{ parameter.key }}: ${{ parameter.value }} 9 | -------------------------------------------------------------------------------- /eng/common/templates-official/post-build/setup-maestro-vars.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml 3 | parameters: 4 | # Specifies whether to use 1ES 5 | is1ESPipeline: true 6 | 7 | ${{ each parameter in parameters }}: 8 | ${{ parameter.key }}: ${{ parameter.value }} -------------------------------------------------------------------------------- /eng/common/templates-official/steps/component-governance.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/component-governance.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates-official/steps/enable-internal-runtimes.yml: -------------------------------------------------------------------------------- 1 | # Obtains internal runtime download credentials and populates the 'dotnetbuilds-internal-container-read-token-base64' 2 | # variable with the base64-encoded SAS token, by default 3 | steps: 4 | - template: /eng/common/core-templates/steps/enable-internal-runtimes.yml 5 | parameters: 6 | is1ESPipeline: true 7 | 8 | ${{ each parameter in parameters }}: 9 | ${{ parameter.key }}: ${{ parameter.value }} 10 | -------------------------------------------------------------------------------- /eng/common/templates-official/steps/enable-internal-sources.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/enable-internal-sources.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} -------------------------------------------------------------------------------- /eng/common/templates-official/steps/generate-sbom.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/generate-sbom.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates-official/steps/get-delegation-sas.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/get-delegation-sas.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates-official/steps/get-federated-access-token.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/get-federated-access-token.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} -------------------------------------------------------------------------------- /eng/common/templates-official/steps/publish-build-artifacts.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: displayName 3 | type: string 4 | default: 'Publish to Build Artifact' 5 | 6 | - name: condition 7 | type: string 8 | default: succeeded() 9 | 10 | - name: artifactName 11 | type: string 12 | 13 | - name: pathToPublish 14 | type: string 15 | 16 | - name: continueOnError 17 | type: boolean 18 | default: false 19 | 20 | - name: publishLocation 21 | type: string 22 | default: 'Container' 23 | 24 | - name: is1ESPipeline 25 | type: boolean 26 | default: true 27 | 28 | - name: retryCountOnTaskFailure 29 | type: string 30 | default: 10 31 | 32 | steps: 33 | - ${{ if ne(parameters.is1ESPipeline, true) }}: 34 | - 'eng/common/templates-official cannot be referenced from a non-1ES managed template': error 35 | - task: 1ES.PublishBuildArtifacts@1 36 | displayName: ${{ parameters.displayName }} 37 | condition: ${{ parameters.condition }} 38 | ${{ if parameters.continueOnError }}: 39 | continueOnError: ${{ parameters.continueOnError }} 40 | inputs: 41 | PublishLocation: ${{ parameters.publishLocation }} 42 | PathtoPublish: ${{ parameters.pathToPublish }} 43 | ${{ if parameters.artifactName }}: 44 | ArtifactName: ${{ parameters.artifactName }} 45 | ${{ if parameters.retryCountOnTaskFailure }}: 46 | retryCountOnTaskFailure: ${{ parameters.retryCountOnTaskFailure }} 47 | -------------------------------------------------------------------------------- /eng/common/templates-official/steps/publish-logs.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/publish-logs.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates-official/steps/publish-pipeline-artifacts.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: is1ESPipeline 3 | type: boolean 4 | default: true 5 | 6 | - name: args 7 | type: object 8 | default: {} 9 | 10 | steps: 11 | - ${{ if ne(parameters.is1ESPipeline, true) }}: 12 | - 'eng/common/templates-official cannot be referenced from a non-1ES managed template': error 13 | - task: 1ES.PublishPipelineArtifact@1 14 | displayName: ${{ coalesce(parameters.args.displayName, 'Publish to Build Artifact') }} 15 | ${{ if parameters.args.condition }}: 16 | condition: ${{ parameters.args.condition }} 17 | ${{ else }}: 18 | condition: succeeded() 19 | ${{ if parameters.args.continueOnError }}: 20 | continueOnError: ${{ parameters.args.continueOnError }} 21 | inputs: 22 | targetPath: ${{ parameters.args.targetPath }} 23 | ${{ if parameters.args.artifactName }}: 24 | artifactName: ${{ parameters.args.artifactName }} 25 | ${{ if parameters.args.properties }}: 26 | properties: ${{ parameters.args.properties }} 27 | ${{ if parameters.args.sbomEnabled }}: 28 | sbomEnabled: ${{ parameters.args.sbomEnabled }} 29 | -------------------------------------------------------------------------------- /eng/common/templates-official/steps/retain-build.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/retain-build.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates-official/steps/send-to-helix.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/send-to-helix.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates-official/steps/source-build.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/source-build.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates-official/steps/source-index-stage1-publish.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/source-index-stage1-publish.yml 3 | parameters: 4 | is1ESPipeline: true 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates-official/variables/pool-providers.yml: -------------------------------------------------------------------------------- 1 | # Select a pool provider based off branch name. Anything with branch name containing 'release' must go into an -Svc pool, 2 | # otherwise it should go into the "normal" pools. This separates out the queueing and billing of released branches. 3 | 4 | # Motivation: 5 | # Once a given branch of a repository's output has been officially "shipped" once, it is then considered to be COGS 6 | # (Cost of goods sold) and should be moved to a servicing pool provider. This allows both separation of queueing 7 | # (allowing release builds and main PR builds to not intefere with each other) and billing (required for COGS. 8 | # Additionally, the pool provider name itself may be subject to change when the .NET Core Engineering Services 9 | # team needs to move resources around and create new and potentially differently-named pools. Using this template 10 | # file from an Arcade-ified repo helps guard against both having to update one's release/* branches and renaming. 11 | 12 | # How to use: 13 | # This yaml assumes your shipped product branches use the naming convention "release/..." (which many do). 14 | # If we find alternate naming conventions in broad usage it can be added to the condition below. 15 | # 16 | # First, import the template in an arcade-ified repo to pick up the variables, e.g.: 17 | # 18 | # variables: 19 | # - template: /eng/common/templates-official/variables/pool-providers.yml 20 | # 21 | # ... then anywhere specifying the pool provider use the runtime variables, 22 | # $(DncEngInternalBuildPool) 23 | # 24 | # pool: 25 | # name: $(DncEngInternalBuildPool) 26 | # image: 1es-windows-2022 27 | 28 | variables: 29 | # Coalesce the target and source branches so we know when a PR targets a release branch 30 | # If these variables are somehow missing, fall back to main (tends to have more capacity) 31 | 32 | # Any new -Svc alternative pools should have variables added here to allow for splitting work 33 | 34 | - name: DncEngInternalBuildPool 35 | value: $[ 36 | replace( 37 | replace( 38 | eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), 39 | True, 40 | 'NetCore1ESPool-Svc-Internal' 41 | ), 42 | False, 43 | 'NetCore1ESPool-Internal' 44 | ) 45 | ] -------------------------------------------------------------------------------- /eng/common/templates-official/variables/sdl-variables.yml: -------------------------------------------------------------------------------- 1 | variables: 2 | # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in 3 | # sync with the packages.config file. 4 | - name: DefaultGuardianVersion 5 | value: 0.109.0 6 | - name: GuardianPackagesConfigFile 7 | value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config -------------------------------------------------------------------------------- /eng/common/templates/job/onelocbuild.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - template: /eng/common/core-templates/job/onelocbuild.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates/job/publish-build-assets.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - template: /eng/common/core-templates/job/publish-build-assets.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates/job/source-build.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - template: /eng/common/core-templates/job/source-build.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates/job/source-index-stage1.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - template: /eng/common/core-templates/job/source-index-stage1.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates/jobs/codeql-build.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - template: /eng/common/core-templates/jobs/codeql-build.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates/jobs/jobs.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - template: /eng/common/core-templates/jobs/jobs.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates/jobs/source-build.yml: -------------------------------------------------------------------------------- 1 | jobs: 2 | - template: /eng/common/core-templates/jobs/source-build.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} -------------------------------------------------------------------------------- /eng/common/templates/post-build/common-variables.yml: -------------------------------------------------------------------------------- 1 | variables: 2 | - template: /eng/common/core-templates/post-build/common-variables.yml 3 | parameters: 4 | # Specifies whether to use 1ES 5 | is1ESPipeline: false 6 | 7 | ${{ each parameter in parameters }}: 8 | ${{ parameter.key }}: ${{ parameter.value }} -------------------------------------------------------------------------------- /eng/common/templates/post-build/post-build.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - template: /eng/common/core-templates/post-build/post-build.yml 3 | parameters: 4 | # Specifies whether to use 1ES 5 | is1ESPipeline: false 6 | 7 | ${{ each parameter in parameters }}: 8 | ${{ parameter.key }}: ${{ parameter.value }} -------------------------------------------------------------------------------- /eng/common/templates/post-build/setup-maestro-vars.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/post-build/setup-maestro-vars.yml 3 | parameters: 4 | # Specifies whether to use 1ES 5 | is1ESPipeline: false 6 | 7 | ${{ each parameter in parameters }}: 8 | ${{ parameter.key }}: ${{ parameter.value }} -------------------------------------------------------------------------------- /eng/common/templates/steps/component-governance.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/component-governance.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates/steps/enable-internal-runtimes.yml: -------------------------------------------------------------------------------- 1 | # Obtains internal runtime download credentials and populates the 'dotnetbuilds-internal-container-read-token-base64' 2 | # variable with the base64-encoded SAS token, by default 3 | 4 | steps: 5 | - template: /eng/common/core-templates/steps/enable-internal-runtimes.yml 6 | parameters: 7 | is1ESPipeline: false 8 | 9 | ${{ each parameter in parameters }}: 10 | ${{ parameter.key }}: ${{ parameter.value }} 11 | -------------------------------------------------------------------------------- /eng/common/templates/steps/enable-internal-sources.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/enable-internal-sources.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} -------------------------------------------------------------------------------- /eng/common/templates/steps/generate-sbom.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/generate-sbom.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates/steps/get-delegation-sas.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/get-delegation-sas.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates/steps/get-federated-access-token.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/get-federated-access-token.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} -------------------------------------------------------------------------------- /eng/common/templates/steps/publish-build-artifacts.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: is1ESPipeline 3 | type: boolean 4 | default: false 5 | 6 | - name: displayName 7 | type: string 8 | default: 'Publish to Build Artifact' 9 | 10 | - name: condition 11 | type: string 12 | default: succeeded() 13 | 14 | - name: artifactName 15 | type: string 16 | 17 | - name: pathToPublish 18 | type: string 19 | 20 | - name: continueOnError 21 | type: boolean 22 | default: false 23 | 24 | - name: publishLocation 25 | type: string 26 | default: 'Container' 27 | 28 | - name: retryCountOnTaskFailure 29 | type: string 30 | default: 10 31 | 32 | steps: 33 | - ${{ if eq(parameters.is1ESPipeline, true) }}: 34 | - 'eng/common/templates cannot be referenced from a 1ES managed template': error 35 | - task: PublishBuildArtifacts@1 36 | displayName: ${{ parameters.displayName }} 37 | condition: ${{ parameters.condition }} 38 | ${{ if parameters.continueOnError }}: 39 | continueOnError: ${{ parameters.continueOnError }} 40 | inputs: 41 | PublishLocation: ${{ parameters.publishLocation }} 42 | PathtoPublish: ${{ parameters.pathToPublish }} 43 | ${{ if parameters.artifactName }}: 44 | ArtifactName: ${{ parameters.artifactName }} 45 | ${{ if parameters.retryCountOnTaskFailure }}: 46 | retryCountOnTaskFailure: ${{ parameters.retryCountOnTaskFailure }} 47 | -------------------------------------------------------------------------------- /eng/common/templates/steps/publish-logs.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/publish-logs.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates/steps/publish-pipeline-artifacts.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: is1ESPipeline 3 | type: boolean 4 | default: false 5 | 6 | - name: args 7 | type: object 8 | default: {} 9 | 10 | steps: 11 | - ${{ if eq(parameters.is1ESPipeline, true) }}: 12 | - 'eng/common/templates cannot be referenced from a 1ES managed template': error 13 | - task: PublishPipelineArtifact@1 14 | displayName: ${{ coalesce(parameters.args.displayName, 'Publish to Build Artifact') }} 15 | ${{ if parameters.args.condition }}: 16 | condition: ${{ parameters.args.condition }} 17 | ${{ else }}: 18 | condition: succeeded() 19 | ${{ if parameters.args.continueOnError }}: 20 | continueOnError: ${{ parameters.args.continueOnError }} 21 | inputs: 22 | targetPath: ${{ parameters.args.targetPath }} 23 | ${{ if parameters.args.artifactName }}: 24 | artifactName: ${{ parameters.args.artifactName }} 25 | ${{ if parameters.args.publishLocation }}: 26 | publishLocation: ${{ parameters.args.publishLocation }} 27 | ${{ if parameters.args.fileSharePath }}: 28 | fileSharePath: ${{ parameters.args.fileSharePath }} 29 | ${{ if parameters.args.Parallel }}: 30 | parallel: ${{ parameters.args.Parallel }} 31 | ${{ if parameters.args.parallelCount }}: 32 | parallelCount: ${{ parameters.args.parallelCount }} 33 | ${{ if parameters.args.properties }}: 34 | properties: ${{ parameters.args.properties }} -------------------------------------------------------------------------------- /eng/common/templates/steps/retain-build.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/retain-build.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates/steps/send-to-helix.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/send-to-helix.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates/steps/source-build.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/source-build.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates/steps/source-index-stage1-publish.yml: -------------------------------------------------------------------------------- 1 | steps: 2 | - template: /eng/common/core-templates/steps/source-index-stage1-publish.yml 3 | parameters: 4 | is1ESPipeline: false 5 | 6 | ${{ each parameter in parameters }}: 7 | ${{ parameter.key }}: ${{ parameter.value }} 8 | -------------------------------------------------------------------------------- /eng/common/templates/variables/pool-providers.yml: -------------------------------------------------------------------------------- 1 | # Select a pool provider based off branch name. Anything with branch name containing 'release' must go into an -Svc pool, 2 | # otherwise it should go into the "normal" pools. This separates out the queueing and billing of released branches. 3 | 4 | # Motivation: 5 | # Once a given branch of a repository's output has been officially "shipped" once, it is then considered to be COGS 6 | # (Cost of goods sold) and should be moved to a servicing pool provider. This allows both separation of queueing 7 | # (allowing release builds and main PR builds to not intefere with each other) and billing (required for COGS. 8 | # Additionally, the pool provider name itself may be subject to change when the .NET Core Engineering Services 9 | # team needs to move resources around and create new and potentially differently-named pools. Using this template 10 | # file from an Arcade-ified repo helps guard against both having to update one's release/* branches and renaming. 11 | 12 | # How to use: 13 | # This yaml assumes your shipped product branches use the naming convention "release/..." (which many do). 14 | # If we find alternate naming conventions in broad usage it can be added to the condition below. 15 | # 16 | # First, import the template in an arcade-ified repo to pick up the variables, e.g.: 17 | # 18 | # variables: 19 | # - template: /eng/common/templates/variables/pool-providers.yml 20 | # 21 | # ... then anywhere specifying the pool provider use the runtime variables, 22 | # $(DncEngInternalBuildPool) and $ (DncEngPublicBuildPool), e.g.: 23 | # 24 | # pool: 25 | # name: $(DncEngInternalBuildPool) 26 | # demands: ImageOverride -equals windows.vs2019.amd64 27 | variables: 28 | - ${{ if eq(variables['System.TeamProject'], 'internal') }}: 29 | - template: /eng/common/templates-official/variables/pool-providers.yml 30 | - ${{ else }}: 31 | # Coalesce the target and source branches so we know when a PR targets a release branch 32 | # If these variables are somehow missing, fall back to main (tends to have more capacity) 33 | 34 | # Any new -Svc alternative pools should have variables added here to allow for splitting work 35 | - name: DncEngPublicBuildPool 36 | value: $[ 37 | replace( 38 | replace( 39 | eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), 40 | True, 41 | 'NetCore-Svc-Public' 42 | ), 43 | False, 44 | 'NetCore-Public' 45 | ) 46 | ] 47 | 48 | - name: DncEngInternalBuildPool 49 | value: $[ 50 | replace( 51 | replace( 52 | eq(contains(coalesce(variables['System.PullRequest.TargetBranch'], variables['Build.SourceBranch'], 'refs/heads/main'), 'release'), 'true'), 53 | True, 54 | 'NetCore1ESPool-Svc-Internal' 55 | ), 56 | False, 57 | 'NetCore1ESPool-Internal' 58 | ) 59 | ] 60 | -------------------------------------------------------------------------------- /eng/common/templates/vmr-build-pr.yml: -------------------------------------------------------------------------------- 1 | trigger: none 2 | pr: 3 | branches: 4 | include: 5 | - main 6 | - release/* 7 | paths: 8 | exclude: 9 | - documentation/* 10 | - README.md 11 | - CODEOWNERS 12 | 13 | variables: 14 | - template: /eng/common/templates/variables/pool-providers.yml@self 15 | 16 | - name: skipComponentGovernanceDetection # we run CG on internal builds only 17 | value: true 18 | 19 | - name: Codeql.Enabled # we run CodeQL on internal builds only 20 | value: false 21 | 22 | resources: 23 | repositories: 24 | - repository: vmr 25 | type: github 26 | name: dotnet/dotnet 27 | endpoint: dotnet 28 | 29 | stages: 30 | - template: /eng/pipelines/templates/stages/vmr-build.yml@vmr 31 | parameters: 32 | isBuiltFromVmr: false 33 | scope: lite 34 | -------------------------------------------------------------------------------- /global.json: -------------------------------------------------------------------------------- 1 | { 2 | "tools": { 3 | "dotnet": "10.0.100-preview.5.25265.106" 4 | }, 5 | "msbuild-sdks": { 6 | "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.25305.3", 7 | "Microsoft.Build.Traversal": "3.4.0" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /hotreload-utils.proj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/Common/TempDirectory.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | using System; 5 | using System.IO; 6 | 7 | namespace Microsoft.DotNet.HotReload.Utils.Common; 8 | 9 | internal class TempDirectory : IDisposable 10 | { 11 | public TempDirectory(bool keep = false, string? dirname = null) 12 | { 13 | string subdir = dirname ?? System.IO.Path.GetRandomFileName(); 14 | Path = System.IO.Path.Combine(System.IO.Path.GetTempPath(), subdir); 15 | Keep = keep; 16 | Directory.CreateDirectory(Path); 17 | } 18 | 19 | public string Path { get; } 20 | public bool Keep { get; set; } 21 | 22 | public void Dispose() 23 | { 24 | if (!Keep) 25 | Directory.Delete(Path, true); 26 | GC.SuppressFinalize(this); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator.BuildTool/Microsoft.DotNet.HotReload.Utils.Generator.BuildTool.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | MSBuildSdk 6 | 7 | Major 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | Microsoft.DotNet.HotReload.Utils.Generator.BuildTool.targets.in 22 | $(IntermediateOutputPath)Microsoft.DotNet.HotReload.Utils.Generator.BuildTool.targets 23 | 24 | 25 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | build/Microsoft.DotNet.HotReload.Utils.Generator.BuildTool.targets 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator.BuildTool/Program.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | return Microsoft.DotNet.HotReload.Utils.Generator.Frontend.Frontend.Main(args); 5 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator.BuildTool/README.md: -------------------------------------------------------------------------------- 1 | # Microsoft.DotNet.HotReload.Utils.Generator.BuildTool # 2 | 3 | Generate deltas as part of an MSBuild project. 4 | 5 | ## How to use it ## 6 | 7 | Starting with an existing SDK-style project, add: 8 | 9 | ```xml 10 | 11 | 12 | 13 | 14 | 15 | deltascript.json 16 | 17 | ``` 18 | 19 | Where the `deltascript.json` file contains the changes to be applied: 20 | 21 | ```json 22 | {"changes": 23 | [ 24 | {"document": "relativePath/to/file.cs", "update": "relativePath/to/file_v1.cs"}, 25 | {"document": "file2.cs", "update": "file2_v2.cs"}, 26 | {"document": "relativePath/to/file.cs", "update": "relativePath/to/file_v3.cs"} 27 | ] 28 | } 29 | ``` 30 | 31 | The tool will run as part of the build after the `Build` target and generate `.dmeta`, `.dil` and `.dpdb` files in `$(OutputPath)`. 32 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator.Data/Microsoft.DotNet.HotReload.Utils.Generator.Data.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator.Data/OutputSummary/OutputSummary.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | using System.Text.Json.Serialization; 5 | 6 | 7 | namespace Microsoft.DotNet.HotReload.Utils.Generator.OutputSummary; 8 | 9 | public class OutputSummary { 10 | [JsonPropertyName("deltas")] 11 | public Delta[]? Deltas {get; init;} 12 | 13 | [JsonExtensionData] 14 | public System.Collections.Generic.Dictionary? Extra {get; init;} 15 | 16 | [JsonConstructor] 17 | public OutputSummary(Delta[]? deltas) { 18 | Deltas = deltas; 19 | } 20 | } 21 | 22 | public class Delta { 23 | [JsonPropertyName("assembly")] 24 | public string? Assembly {get; init;} 25 | [JsonPropertyName("metadata")] 26 | public string? Metadata {get; init;} 27 | [JsonPropertyName("il")] 28 | public string? IL {get; init;} 29 | [JsonPropertyName("pdb")] 30 | public string? Pdb {get; init;} 31 | 32 | [JsonConstructor] 33 | public Delta (string? assembly, string? metadata, string? il, string? pdb) { 34 | Assembly = assembly; 35 | Metadata = metadata; 36 | IL = il; 37 | Pdb = pdb; 38 | } 39 | 40 | [JsonExtensionData] 41 | public System.Collections.Generic.Dictionary? Extra {get; set;} 42 | } 43 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator.Data/Script/Json/Script.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | using System.Text.Json.Serialization; 5 | 6 | namespace Microsoft.DotNet.HotReload.Utils.Generator.Script.Json; 7 | public class Script { 8 | 9 | [JsonConverter(typeof(ScriptCapabilitiesConverter))] 10 | public string? Capabilities {get; init;} 11 | public Change[]? Changes {get; init;} 12 | 13 | [System.Text.Json.Serialization.JsonConstructor] 14 | public Script (string? capabilities, Change[]? changes) { 15 | Capabilities = capabilities; 16 | Changes = changes; 17 | } 18 | 19 | } 20 | 21 | public class Change { 22 | public string Document {get; init;} 23 | public string Update {get; init;} 24 | 25 | [System.Text.Json.Serialization.JsonConstructor] 26 | public Change (string document, string update) { 27 | Document = document; 28 | Update = update; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator.Data/Script/Json/ScriptCapabilitiesConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text.Json; 3 | using System.Text.Json.Serialization; 4 | 5 | 6 | namespace Microsoft.DotNet.HotReload.Utils.Generator.Script.Json; 7 | 8 | /// Deserialize capabilities as either a JSON string value, or an array of JSON string values 9 | public class ScriptCapabilitiesConverter : JsonConverter { 10 | public override bool HandleNull => true; 11 | 12 | public ScriptCapabilitiesConverter() {} 13 | 14 | public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 15 | => reader.TokenType switch { 16 | JsonTokenType.Null => string.Empty, 17 | JsonTokenType.String => reader.GetString(), 18 | JsonTokenType.StartArray => ReadCapsArray (ref reader, options), 19 | _ => throw new JsonException(), 20 | }; 21 | 22 | private static string ReadCapsArray(ref Utf8JsonReader reader, JsonSerializerOptions options) { 23 | var elems = JsonSerializer.Deserialize (ref reader, options); 24 | if (elems == null) 25 | throw new JsonException(); 26 | return String.Join(' ', elems); 27 | } 28 | public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) => writer.WriteStringValue(value); 29 | } 30 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator.Data/UpdateHandlerInfo.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | using System.Collections.Immutable; 5 | using System.Text.Json.Serialization; 6 | 7 | 8 | namespace Microsoft.DotNet.HotReload.Utils.Generator; 9 | 10 | public class UpdateHandlerInfo { 11 | 12 | [JsonPropertyName("updatedTypes")] 13 | public ImmutableArray UpdatedTypes {get; init;} 14 | 15 | public UpdateHandlerInfo(ImmutableArray updatedTypes) { 16 | UpdatedTypes = updatedTypes; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator.Frontend/Microsoft.DotNet.HotReload.Utils.Generator.Frontend.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator.Tasks/Microsoft.DotNet.HotReload.Utils.Generator.Tasks.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator/BaselineArtifacts.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | using Microsoft.CodeAnalysis; 5 | 6 | namespace Microsoft.DotNet.HotReload.Utils.Generator; 7 | 8 | /// What we know about the base compilation 9 | /// 10 | /// BaselineSolution: the solution we're working on 11 | /// BaselineProjectId: the project we're working on; FIXME: need to be more clever when there are project references 12 | /// BaselineOutputAsmPath: absolute path of the baseline assembly 13 | /// DocResolver: a map from document ids to documents 14 | /// ChangeMakerService: A stateful encapsulatio of the series of changes that have been made to the baseline 15 | public record struct BaselineArtifacts (Solution BaselineSolution, ProjectId BaselineProjectId, string BaselineOutputAsmPath, DocResolver DocResolver, EnC.ChangeMakerService ChangeMakerService); 16 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator/Config.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | using System.Collections.Generic; 5 | using System.IO; 6 | 7 | namespace Microsoft.DotNet.HotReload.Utils.Generator; 8 | 9 | public class Config 10 | { 11 | 12 | public static ConfigBuilder Builder () => new (); 13 | 14 | public class ConfigBuilder { 15 | internal ConfigBuilder () {} 16 | 17 | public bool Live {get; set;} = false; 18 | 19 | public List> Properties {get; set;} = new List> (); 20 | public string ProjectPath {get; set; } = ""; 21 | 22 | public string ScriptPath {get; set; } = ""; 23 | 24 | public string OutputSummaryPath {get; set; } = ""; 25 | public Config Bake () { 26 | return new MsbuildConfig(this); 27 | } 28 | 29 | public List EditAndContinueCapabilities {get; set; } = new List(); 30 | 31 | public bool NoWarnUnknownCapabilities {get; set;} = false; 32 | } 33 | 34 | protected Config (ConfigBuilder builder) { 35 | Live = builder.Live; 36 | Properties = builder.Properties; 37 | ProjectPath = builder.ProjectPath; 38 | ScriptPath = builder.ScriptPath; 39 | OutputSummaryPath = builder.OutputSummaryPath; 40 | EditAndContinueCapabilities = builder.EditAndContinueCapabilities.ToArray(); 41 | NoWarnUnknownCapabilities = builder.NoWarnUnknownCapabilities; 42 | } 43 | 44 | public bool Live { get; } 45 | 46 | /// Additional properties for msbuild 47 | public IReadOnlyList> Properties { get; } 48 | 49 | 50 | /// the csproj for this project 51 | public string ProjectPath { get; } 52 | 53 | /// the files to watch for live changes 54 | public string LiveCodingWatchPattern { get => "*.cs"; } 55 | 56 | /// the directory to watch for live changes 57 | public string LiveCodingWatchDir { get => Path.GetDirectoryName(ProjectPath) ?? "."; } 58 | 59 | /// the path of a JSON script to drive the delta generation 60 | public string ScriptPath { get; } 61 | 62 | /// A path for a JSON file to collect the produced artifacts 63 | public string OutputSummaryPath { get; } 64 | 65 | /// A set of strings specifying edit and continue capabilities to pass to Roslyn 66 | public string[] EditAndContinueCapabilities { get; } 67 | 68 | /// If 'true' don't print a warning if a capability is not known. 69 | public bool NoWarnUnknownCapabilities {get; } 70 | } 71 | 72 | internal class MsbuildConfig : Config { 73 | internal MsbuildConfig (ConfigBuilder builder) : base (builder) {} 74 | } 75 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator/Delta.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | using Microsoft.CodeAnalysis; 5 | 6 | namespace Microsoft.DotNet.HotReload.Utils.Generator; 7 | 8 | /// A Delta represents an input that is used to produce the metadata, IL and PDB emitted differences. 9 | /// It contains a Change which identifies the source document that changed and its updated contents 10 | public readonly record struct Delta (Plan.Change Change); 11 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator/DeltaNaming.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | namespace Microsoft.DotNet.HotReload.Utils.Generator; 5 | 6 | /// Properties describing names of the artifacts for a given revision of a baseline assembly 7 | public class DeltaNaming { 8 | 9 | readonly string _baseAssemblyPath; 10 | readonly int _rev; 11 | 12 | public DeltaNaming (string baseAssemblyPath, int rev) { 13 | _rev = rev; 14 | _baseAssemblyPath = baseAssemblyPath; 15 | } 16 | public string Dmeta => _baseAssemblyPath + "." + Rev + ".dmeta"; 17 | public string Dil => _baseAssemblyPath + "." + Rev + ".dil"; 18 | public string Dpdb => _baseAssemblyPath + "." + Rev + ".dpdb"; 19 | 20 | public string UpdateHandlerInfo => _baseAssemblyPath + "." + Rev + ".handler.json"; 21 | public int Rev => _rev; 22 | 23 | public DeltaNaming Next() 24 | { 25 | return new DeltaNaming(_baseAssemblyPath, Rev+1); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator/DeltaOutputStreams.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | using System; 5 | using System.IO; 6 | using System.Threading.Tasks; 7 | 8 | namespace Microsoft.DotNet.HotReload.Utils.Generator; 9 | public sealed class DeltaOutputStreams : IAsyncDisposable { 10 | public Stream MetaStream {get; private set;} 11 | public Stream IlStream {get; private set;} 12 | public Stream PdbStream {get; private set;} 13 | 14 | public Stream UpdateHandlerInfoStream {get; private set;} 15 | 16 | public DeltaOutputStreams(Stream dmeta, Stream dil, Stream dpdb, Stream updateHandlerInfo) { 17 | MetaStream = dmeta; 18 | IlStream = dil; 19 | PdbStream = dpdb; 20 | UpdateHandlerInfoStream = updateHandlerInfo; 21 | } 22 | 23 | public void Dispose () { 24 | MetaStream?.Dispose(); 25 | IlStream?.Dispose(); 26 | PdbStream?.Dispose(); 27 | UpdateHandlerInfoStream?.Dispose(); 28 | } 29 | 30 | public async ValueTask DisposeAsync () { 31 | if (MetaStream != null) await MetaStream.DisposeAsync(); 32 | if (IlStream != null) await IlStream.DisposeAsync(); 33 | if (PdbStream != null) await PdbStream.DisposeAsync(); 34 | if (UpdateHandlerInfoStream != null) await UpdateHandlerInfoStream.DisposeAsync(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator/DiffyException.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | using System; 5 | 6 | namespace Microsoft.DotNet.HotReload.Utils.Generator; 7 | 8 | public class DiffyException : Exception { 9 | public int ExitStatus { get; } 10 | 11 | public DiffyException(int exitStatus) : base () { 12 | ExitStatus = exitStatus; 13 | } 14 | 15 | public DiffyException (string message, int exitStatus) : base (message) { 16 | ExitStatus = exitStatus; 17 | } 18 | 19 | public DiffyException (string message, Exception innerException, int exitStatus) : base (message, innerException) { 20 | ExitStatus = exitStatus; 21 | } 22 | } 23 | 24 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator/DocResolver.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | using System.IO; 5 | using System.Collections.Generic; 6 | using System.Collections.Immutable; 7 | using System.Diagnostics.CodeAnalysis; 8 | 9 | using Microsoft.CodeAnalysis; 10 | 11 | namespace Microsoft.DotNet.HotReload.Utils.Generator; 12 | 13 | /// Maps a source file path to a DocumentId in a given Project 14 | public class DocResolver { 15 | 16 | private readonly Project project; 17 | 18 | private readonly ImmutableDictionary docMap; 19 | public DocResolver(Project project) { 20 | this.project = project; 21 | this.docMap = BuildDocMap (project.Documents); 22 | } 23 | 24 | public Project Project { get => project; } 25 | 26 | private static ImmutableDictionary BuildDocMap (IEnumerable docs) 27 | { 28 | var builder = ImmutableDictionary.CreateBuilder(); 29 | foreach (var doc in docs) { 30 | var key = doc.FilePath; 31 | var value = doc.Id; 32 | var kvp = KeyValuePair.Create(key!, value); 33 | builder.Add(kvp); 34 | } 35 | return builder.ToImmutable(); 36 | } 37 | 38 | public bool TryResolveDocumentId (string relativePath, [NotNullWhen(true)] out DocumentId id) { 39 | var absolutePath = Path.GetFullPath(relativePath); 40 | return docMap.TryGetValue(absolutePath, out id!); 41 | } 42 | 43 | } 44 | 45 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator/EditAndContinueCapabilitiesParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text.RegularExpressions; 4 | 5 | namespace Microsoft.DotNet.HotReload.Utils.Generator; 6 | 7 | public static class EditAndContinueCapabilitiesParser { 8 | 9 | public readonly struct Token { 10 | public readonly string Value {get; init;} 11 | } 12 | static public readonly Regex capabilitiesTokenizer = new (@"^\s*(?:(\S+)\s+)*(\S+)?$", RegexOptions.CultureInvariant); 13 | public static IEnumerable Tokenize (string capabilities) 14 | { 15 | Match match = capabilitiesTokenizer.Match (capabilities); 16 | if (!match.Success) 17 | yield break; 18 | foreach (Capture c in match.Groups[1].Captures) { 19 | yield return new Token { Value = c.Value }; 20 | } 21 | foreach (Capture c in match.Groups[2].Captures) { 22 | yield return new Token { Value = c.Value }; 23 | } 24 | } 25 | 26 | public static IEnumerable Tokenize (IEnumerable capabilities) 27 | { 28 | foreach (var cap in capabilities) { 29 | foreach (var token in Tokenize(cap)) 30 | yield return token; 31 | } 32 | } 33 | 34 | internal static (IEnumerable capabilities, IEnumerable unknowns) Parse (IEnumerable tokens) 35 | { 36 | List unknowns = new(); 37 | List capabilities = new(); 38 | foreach (var tok in tokens) 39 | { 40 | if (ParseToken (tok, out var cap)) { 41 | capabilities.Add (cap); 42 | } else { 43 | unknowns.Add (tok.Value); 44 | } 45 | } 46 | return (capabilities, unknowns); 47 | } 48 | 49 | internal static (IEnumerable capabilities, IEnumerable unknowns) Parse (string capabilities) 50 | { 51 | return Parse(Tokenize(capabilities)); 52 | } 53 | 54 | internal static (IEnumerable capabilities, IEnumerable unknowns) Parse (IEnumerable capabilities) 55 | { 56 | return Parse(Tokenize(capabilities)); 57 | } 58 | 59 | internal static bool ParseToken (Token token, out EnC.EditAndContinueCapabilities res) => 60 | Enum.TryParse(token.Value, ignoreCase: true, out res); 61 | 62 | } 63 | 64 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator/EnC/ChangeMaker.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | using System; 5 | using System.Runtime.Loader; 6 | using System.Reflection; 7 | 8 | namespace Microsoft.DotNet.HotReload.Utils.Generator.EnC; 9 | 10 | // 11 | // Inspired by https://github.com/dotnet/roslyn/issues/8962 12 | public class ChangeMaker { 13 | private const string codeAnalysisFeaturesAssemblyName = "Microsoft.CodeAnalysis.Features"; 14 | 15 | private const string capabilitiesTypeName = "Microsoft.CodeAnalysis.EditAndContinue.EditAndContinueCapabilities"; 16 | 17 | readonly record struct Reflected (Type Capabilities); 18 | 19 | private readonly Reflected _reflected; 20 | 21 | public Type EditAncContinueCapabilitiesType => _reflected.Capabilities; 22 | 23 | public ChangeMaker () { 24 | _reflected = ReflectionInit(); 25 | } 26 | // Get all the Roslyn stuff we need 27 | private static Reflected ReflectionInit () 28 | { 29 | 30 | var an = new AssemblyName(codeAnalysisFeaturesAssemblyName); 31 | var assm = AssemblyLoadContext.Default.LoadFromAssemblyName(an); 32 | 33 | var caps = assm.GetType (capabilitiesTypeName); 34 | 35 | if (caps == null) { 36 | throw new Exception ("Couldn't find EditAndContinueCapabilities type"); 37 | } 38 | 39 | return new Reflected() { Capabilities = caps, 40 | }; 41 | } 42 | 43 | /// Convert my EditAndContinueCapabilities enum value to 44 | /// [Microsoft.CodeAnalysis.Features]Microsoft.CodeAnalysis.EditAndContinue.EditAndContinueCapabilities 45 | public object ConvertCapabilities (EditAndContinueCapabilities myCaps) 46 | { 47 | int i = (int)myCaps; 48 | object theirCaps = Enum.ToObject(_reflected.Capabilities, i); 49 | return theirCaps; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator/EnC/EditAndContinueCapabilities.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Microsoft.DotNet.HotReload.Utils.Generator.EnC; 4 | 5 | /// Copied from https://github.com/dotnet/roslyn/blob/e8e6d30fe462edd48ce13f6438e91d26876c17bb/src/Features/Core/Portable/EditAndContinue/EditAndContinueCapabilities.cs 6 | /// Keep in sync 7 | /// 8 | /// The capabilities that the runtime has with respect to edit and continue 9 | /// 10 | [Flags] 11 | public enum EditAndContinueCapabilities 12 | { 13 | None = 0, 14 | 15 | /// 16 | /// Edit and continue is generally available with the set of capabilities that Mono 6, .NET Framework and .NET 5 have in common. 17 | /// 18 | Baseline = 1 << 0, 19 | 20 | /// 21 | /// Adding a static or instance method to an existing type. 22 | /// 23 | AddMethodToExistingType = 1 << 1, 24 | 25 | /// 26 | /// Adding a static field to an existing type. 27 | /// 28 | AddStaticFieldToExistingType = 1 << 2, 29 | 30 | /// 31 | /// Adding an instance field to an existing type. 32 | /// 33 | AddInstanceFieldToExistingType = 1 << 3, 34 | 35 | /// 36 | /// Creating a new type definition. 37 | /// 38 | NewTypeDefinition = 1 << 4, 39 | /// 40 | /// Adding, updating and deleting of custom attributes (as distinct from pseudo-custom attributes) 41 | /// 42 | ChangeCustomAttributes = 1 << 5, 43 | 44 | /// 45 | /// Whether the runtime supports updating the Param table, and hence related edits (eg parameter renames) 46 | /// 47 | UpdateParameters = 1 << 6, 48 | 49 | /// 50 | /// Adding a static or instance method, property or event to an existing type (without backing fields), such that the method and/or the type are generic. 51 | /// 52 | GenericAddMethodToExistingType = 1 << 7, 53 | 54 | /// 55 | /// Updating an existing static or instance method, property or event (without backing fields) that is generic and/or contained in a generic type. 56 | /// 57 | GenericUpdateMethod = 1 << 8, 58 | 59 | /// 60 | /// Adding a static or instance field to an existing generic type. 61 | /// 62 | GenericAddFieldToExistingType = 1 << 9, 63 | 64 | /// 65 | /// The runtime supports adding to InterfaceImpl table. 66 | /// 67 | AddExplicitInterfaceImplementation = 1 << 10, 68 | 69 | AddFieldRva = 1 << 11, 70 | } 71 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator/Microsoft.DotNet.HotReload.Utils.Generator.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | runtime; build; native; contentfiles; analyzers; buildtransitive 6 | all 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator/Plan/Change.cs: -------------------------------------------------------------------------------- 1 | 2 | // Licensed to the .NET Foundation under one or more agreements. 3 | // The .NET Foundation licenses this file to you under the MIT license. 4 | 5 | namespace Microsoft.DotNet.HotReload.Utils.Generator.Plan; 6 | 7 | /// A plan is just a collection of changes 8 | /// where each change is some identification of the base document and 9 | /// some representation of the update. 10 | /// 11 | /// For live coding, the collection will be an IAsyncEnumerable>, 12 | /// for a scripted plan it will be some parsed immutable list of changes. 13 | /// 14 | /// Initially the changes are just Change, but then DocResolve will 15 | /// change it to a Chamge. 16 | public readonly record struct Change(TDoc Document, TUpdate Update); 17 | 18 | public static class Change { 19 | public static Change Create(TDoc doc, TUpdate update) { 20 | return new Change(doc, update); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator/Runners/LiveRunner.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Threading; 8 | using System.Threading.Tasks; 9 | using System.Runtime.CompilerServices; 10 | 11 | namespace Microsoft.DotNet.HotReload.Utils.Generator.Runners; 12 | 13 | /// Generate deltas by watching for changes to the source files of the project 14 | public class LiveRunner : Runner { 15 | public LiveRunner (Config config) : base (config) { } 16 | 17 | protected override Task PrepareToRun (CancellationToken ct = default) => Task.CompletedTask; 18 | public override IAsyncEnumerable SetupDeltas (BaselineArtifacts baselineArtifacts, CancellationToken ct = default) 19 | { 20 | return Livecoding (baselineArtifacts, config.LiveCodingWatchDir, config.LiveCodingWatchPattern, ct); 21 | } 22 | 23 | protected override bool PrepareCapabilitiesCore (out EnC.EditAndContinueCapabilities caps) { 24 | caps = EnC.EditAndContinueCapabilities.None; 25 | return false; 26 | } 27 | private static async IAsyncEnumerable Livecoding (BaselineArtifacts baselineArtifacts, string watchDir, string pattern, [EnumeratorCancellation] CancellationToken cancellationToken= default) { 28 | var last = DateTime.UtcNow; 29 | var interval = TimeSpan.FromMilliseconds(250); /* FIXME: make this configurable */ 30 | var docResolver = baselineArtifacts.DocResolver; 31 | var baselineProjectId = baselineArtifacts.BaselineProjectId; 32 | 33 | using var fswgen = new Util.FSWGen (watchDir, pattern); 34 | await foreach (var fsevent in fswgen.Watch(cancellationToken).ConfigureAwait(false)) { 35 | if ((fsevent.ChangeType & WatcherChangeTypes.Changed) != 0) { 36 | var e = DateTime.UtcNow; 37 | Console.WriteLine($"change in {fsevent.FullPath} is a {fsevent.ChangeType} at {e}"); 38 | if (e - last < interval) { 39 | Console.WriteLine($"too soon {e-last}"); 40 | continue; 41 | } 42 | Console.WriteLine($"more than 250ms since last change"); 43 | last = e; 44 | var fp = fsevent.FullPath; 45 | if (!docResolver.TryResolveDocumentId(fp, out var id)) { 46 | Console.WriteLine ($"ignoring change in {fp} which is not in {baselineProjectId}"); 47 | continue; 48 | } 49 | 50 | yield return new Delta (Plan.Change.Create(id, fp)); 51 | } 52 | } 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/Microsoft.DotNet.HotReload.Utils.Generator/Script/Json/Parsing.cs: -------------------------------------------------------------------------------- 1 | // Licensed to the .NET Foundation under one or more agreements. 2 | // The .NET Foundation licenses this file to you under the MIT license. 3 | 4 | using System; 5 | using System.Collections.Generic; 6 | using System.IO; 7 | using System.Linq; 8 | using System.Text.Json; 9 | using System.Threading.Tasks; 10 | 11 | using CancellationToken = System.Threading.CancellationToken; 12 | 13 | namespace Microsoft.DotNet.HotReload.Utils.Generator.Script.Json; 14 | 15 | /// Read a diff script from a json file 16 | public class Parser { 17 | 18 | public readonly string Path; 19 | private readonly string _absDir; 20 | public Parser (string path) { 21 | Path = path; 22 | _absDir = System.IO.Path.GetDirectoryName(System.IO.Path.GetFullPath(path))!; 23 | } 24 | public async ValueTask ReadRawAsync (Stream stream, CancellationToken ct = default) { 25 | var options = new JsonSerializerOptions { 26 | ReadCommentHandling = JsonCommentHandling.Skip, 27 | AllowTrailingCommas = true, 28 | PropertyNameCaseInsensitive = true, 29 | }; 30 | try { 31 | var result = await JsonSerializer.DeserializeAsync