├── .dockerignore
├── .editorconfig
├── .gitattributes
├── .gitignore
├── CODE-OF-CONDUCT.md
├── CONTRIBUTING.md
├── Directory.Build.props
├── Directory.Build.targets
├── Directory.Packages.props
├── LICENSE.txt
├── Microsoft.Crank.sln
├── NOTICE.txt
├── NuGet.config
├── README.md
├── azure-pipelines-release.yml
├── azure-pipelines.yml
├── azure-pr-pipelines.yml
├── build.cmd
├── build.sh
├── docker
└── agent
│ ├── Dockerfile
│ ├── build.sh
│ ├── run.sh
│ └── stop.sh
├── docs
├── README.md
├── benchmarking_docker.md
├── development.md
├── dotnet_versions.md
├── event_counters.md
├── getting_started.md
├── local_application.md
├── measurements.md
├── microbenchmarks.md
├── post_processing.md
├── precommands.md
├── reference
│ ├── architecture.md
│ └── benchmarks.svg
├── setup_linux.md
└── storing_results.md
├── eng
├── Build.props
├── PoliCheckExclusions.xml
├── Publishing.props
├── Signing.props
├── Version.Details.xml
├── Versions.props
├── common
│ ├── BuildConfiguration
│ │ └── build-configuration.json
│ ├── CIBuild.cmd
│ ├── PSScriptAnalyzerSettings.psd1
│ ├── README.md
│ ├── SetupNugetSources.ps1
│ ├── SetupNugetSources.sh
│ ├── build.ps1
│ ├── build.sh
│ ├── cibuild.sh
│ ├── cross
│ │ ├── arm
│ │ │ ├── sources.list.bionic
│ │ │ ├── sources.list.focal
│ │ │ ├── sources.list.jammy
│ │ │ ├── sources.list.jessie
│ │ │ ├── sources.list.xenial
│ │ │ ├── sources.list.zesty
│ │ │ └── tizen
│ │ │ │ └── tizen.patch
│ │ ├── arm64
│ │ │ ├── sources.list.bionic
│ │ │ ├── sources.list.buster
│ │ │ ├── sources.list.focal
│ │ │ ├── sources.list.jammy
│ │ │ ├── sources.list.stretch
│ │ │ ├── sources.list.xenial
│ │ │ ├── sources.list.zesty
│ │ │ └── tizen
│ │ │ │ └── tizen.patch
│ │ ├── armel
│ │ │ ├── armel.jessie.patch
│ │ │ ├── sources.list.jessie
│ │ │ └── tizen
│ │ │ │ └── tizen.patch
│ │ ├── armv6
│ │ │ └── sources.list.buster
│ │ ├── build-android-rootfs.sh
│ │ ├── build-rootfs.sh
│ │ ├── ppc64le
│ │ │ └── sources.list.bionic
│ │ ├── riscv64
│ │ │ └── sources.list.sid
│ │ ├── s390x
│ │ │ └── sources.list.bionic
│ │ ├── tizen-build-rootfs.sh
│ │ ├── tizen-fetch.sh
│ │ └── toolchain.cmake
│ ├── 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-tool.ps1
│ ├── pipeline-logging-functions.ps1
│ ├── pipeline-logging-functions.sh
│ ├── post-build
│ │ ├── add-build-to-channel.ps1
│ │ ├── check-channel-consistency.ps1
│ │ ├── nuget-validation.ps1
│ │ ├── post-build-utils.ps1
│ │ ├── publish-using-darc.ps1
│ │ ├── sourcelink-validation.ps1
│ │ ├── symbols-validation.ps1
│ │ └── trigger-subscriptions.ps1
│ ├── retain-build.ps1
│ ├── sdk-task.ps1
│ ├── 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
│ ├── 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
│ │ │ └── trigger-subscription.yml
│ │ ├── steps
│ │ │ ├── add-build-to-channel.yml
│ │ │ ├── build-reason.yml
│ │ │ ├── component-governance.yml
│ │ │ ├── enable-internal-runtimes.yml
│ │ │ ├── execute-codeql.yml
│ │ │ ├── execute-sdl.yml
│ │ │ ├── generate-sbom.yml
│ │ │ ├── get-delegation-sas.yml
│ │ │ ├── get-federated-access-token.yml
│ │ │ ├── publish-logs.yml
│ │ │ ├── retain-build.yml
│ │ │ ├── send-to-helix.yml
│ │ │ └── source-build.yml
│ │ └── variables
│ │ │ ├── pool-providers.yml
│ │ │ └── sdl-variables.yml
│ ├── templates
│ │ ├── job
│ │ │ ├── execute-sdl.yml
│ │ │ ├── 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
│ │ │ └── trigger-subscription.yml
│ │ ├── steps
│ │ │ ├── add-build-to-channel.yml
│ │ │ ├── build-reason.yml
│ │ │ ├── component-governance.yml
│ │ │ ├── enable-internal-runtimes.yml
│ │ │ ├── execute-codeql.yml
│ │ │ ├── execute-sdl.yml
│ │ │ ├── generate-sbom.yml
│ │ │ ├── get-delegation-sas.yml
│ │ │ ├── get-federated-access-token.yml
│ │ │ ├── publish-logs.yml
│ │ │ ├── retain-build.yml
│ │ │ ├── run-on-unix.yml
│ │ │ ├── run-on-windows.yml
│ │ │ ├── run-script-ifequalelse.yml
│ │ │ ├── send-to-helix.yml
│ │ │ ├── source-build.yml
│ │ │ ├── telemetry-end.yml
│ │ │ └── telemetry-start.yml
│ │ └── variables
│ │ │ ├── pool-providers.yml
│ │ │ └── sdl-variables.yml
│ ├── tools.ps1
│ └── tools.sh
└── dependencies.props
├── global.json
├── samples
├── hello
│ ├── Program.cs
│ ├── Startup.cs
│ ├── appsettings.Development.json
│ ├── appsettings.json
│ ├── hello.benchmarks.yml
│ └── hello.csproj
├── local
│ └── local.benchmarks.yml
├── micro
│ ├── Md5VsSha256.cs
│ ├── Program.cs
│ ├── dotnet.benchmarks.yml
│ ├── micro.benchmarks.yml
│ └── micro.csproj
├── netty
│ └── netty.benchmarks.yml
├── post
│ ├── Program.cs
│ └── post.csproj
├── precommand
│ └── precommand.benchmarks.yml
└── scripts
│ └── scripts.benchmarks.yml
├── src
├── Microsoft.Crank.Agent
│ ├── CGroup.cs
│ ├── CGroupV1.cs
│ ├── CGroupV2.cs
│ ├── CompositeRelayServer.cs
│ ├── Controllers
│ │ ├── HomeController.cs
│ │ └── JobsController.cs
│ ├── Dumper.Windows.cs
│ ├── Dumper.cs
│ ├── GZipFileResult.cs
│ ├── Git.cs
│ ├── JobContext.cs
│ ├── JobResult.cs
│ ├── JobsApis.cs
│ ├── Log.cs
│ ├── MachineCounters
│ │ ├── MachineCountersController.cs
│ │ ├── MachineCountersEventSource.cs
│ │ └── OS
│ │ │ ├── IMachinePerformanceCounterEmitter.cs
│ │ │ ├── LinuxMachineCpuUsageEmitter.cs
│ │ │ ├── WindowsMachineCpuUsageEmitter.cs
│ │ │ └── WindowsProcessCpuTimeEmitter.cs
│ ├── Measurements.cs
│ ├── Microsoft.Crank.Agent.csproj
│ ├── MstatDumper.cs
│ ├── NativeMethods.txt
│ ├── PackageTypes.cs
│ ├── ProcessResult.cs
│ ├── ProcessUtil.cs
│ ├── README.md
│ ├── Repository
│ │ ├── IIdentifiable.cs
│ │ ├── IJobRepository.cs
│ │ └── InMemoryJobRepository.cs
│ ├── Startup.cs
│ ├── TraceExtensions.cs
│ ├── WindowsLimiter.cs
│ └── applicationHost.config
├── Microsoft.Crank.AzureDevOpsWorker
│ ├── DevopsMessage.cs
│ ├── DotNetToolSettings.xml
│ ├── Job.cs
│ ├── JobPayload.cs
│ ├── Microsoft.Crank.AzureDevOpsWorker.csproj
│ ├── ProcessResult.cs
│ ├── Program.cs
│ ├── Records.cs
│ ├── RetryHandler.cs
│ └── TimeSpanConverter.cs
├── Microsoft.Crank.Controller
│ ├── Configuration.cs
│ ├── ControllerException.cs
│ ├── CounterProfile.cs
│ ├── Documentation.cs
│ ├── DotNetToolSettings.xml
│ ├── ExcludeOptions.cs
│ ├── ExecutionResult.cs
│ ├── Headers.cs
│ ├── Ignore
│ │ ├── IgnoreFile.cs
│ │ └── IgnoreRule.cs
│ ├── JobConnection.cs
│ ├── JobDeadlockException.cs
│ ├── JobDefinition.cs
│ ├── JobSerializer.cs
│ ├── JobView.cs
│ ├── JsonTypeResolver.cs
│ ├── Log.cs
│ ├── Microsoft.Crank.Controller.csproj
│ ├── ProcessResult.cs
│ ├── ProcessUtil.cs
│ ├── Program.cs
│ ├── README.md
│ ├── ResultComparer.cs
│ ├── ResultTable.cs
│ ├── ScriptConsole.cs
│ ├── ScriptFile.cs
│ ├── VariableParser.cs
│ ├── VersionChecker.cs
│ ├── WebUtils.cs
│ ├── benchmarks.schema.json
│ └── default.config.yml
├── Microsoft.Crank.EventSources
│ ├── BenchmarksEventSource.cs
│ ├── Microsoft.Crank.EventSources.csproj
│ └── Operations.cs
├── Microsoft.Crank.JobOjectWrapper
│ ├── Microsoft.Crank.JobObjectWrapper.csproj
│ └── Program.cs
├── Microsoft.Crank.Jobs.Bombardier
│ ├── Microsoft.Crank.Jobs.Bombardier.csproj
│ ├── Program.cs
│ └── bombardier.yml
├── Microsoft.Crank.Jobs.H2Load
│ ├── Microsoft.Crank.Jobs.H2Load.csproj
│ ├── Program.cs
│ └── h2load.yml
├── Microsoft.Crank.Jobs.HttpClient
│ ├── Microsoft.Crank.Jobs.HttpClient.csproj
│ ├── Program.cs
│ ├── Runner.cs
│ ├── ScriptConsole.cs
│ ├── Timeline.cs
│ ├── TimelineFactory.cs
│ ├── WorkerResult.cs
│ ├── httpclient.yml
│ └── scripts
│ │ ├── log.js
│ │ ├── script.js
│ │ └── urls.js
├── Microsoft.Crank.Jobs.K6
│ ├── Microsoft.Crank.Jobs.K6.csproj
│ ├── Program.cs
│ ├── k6.yml
│ └── scripts
│ │ └── default.js
├── Microsoft.Crank.Jobs.PipeliningClient
│ ├── HttpConnection.cs
│ ├── HttpResponse.cs
│ ├── Microsoft.Crank.Jobs.PipeliningClient.csproj
│ ├── Program.cs
│ ├── SequenceReaderExtensions.cs
│ ├── WorkerResult.cs
│ └── pipelining.yml
├── Microsoft.Crank.Jobs.Wrk
│ ├── Microsoft.Crank.Jobs.Wrk.csproj
│ ├── Program.cs
│ ├── WrkProcess.cs
│ ├── scripts
│ │ └── pipeline.lua
│ └── wrk.yml
├── Microsoft.Crank.Jobs.Wrk2
│ ├── Microsoft.Crank.Jobs.Wrk2.csproj
│ ├── Program.cs
│ └── wrk2.yml
├── Microsoft.Crank.Models
│ ├── Attachment.cs
│ ├── AttachmentViewModel.cs
│ ├── CommandDefinition.cs
│ ├── Database.cs
│ ├── Dependency.cs
│ ├── DotnetCounter.cs
│ ├── DumpTypeOption.cs
│ ├── EnvironmentData.cs
│ ├── Job.cs
│ ├── JobResults.cs
│ ├── JobState.cs
│ ├── JobStatistics.cs
│ ├── Measurement.cs
│ ├── MeasurementMetadata.cs
│ ├── Microsoft.Crank.Models.csproj
│ ├── OperatingSystem.cs
│ ├── RollingLog.cs
│ ├── Scheme.cs
│ ├── ScriptType.cs
│ ├── Security
│ │ ├── CertificateOptions.cs
│ │ └── CertificateOptionsExtensions.cs
│ ├── Source.cs
│ └── WebHost.cs
├── Microsoft.Crank.PullRequestBot
│ ├── BotOptions.cs
│ ├── Command.cs
│ ├── Configuration.cs
│ ├── CredentialsHelper.cs
│ ├── JsonTypeResolver.cs
│ ├── Microsoft.Crank.PullRequestBot.csproj
│ ├── Program.cs
│ ├── PullRequestBotException.cs
│ ├── README.md
│ ├── pullrequestbot.schema.json
│ ├── sample.config.json
│ └── sample.config.yml
└── Microsoft.Crank.RegressionBot
│ ├── BotOptions.cs
│ ├── Configuration.cs
│ ├── CredentialsHelper.cs
│ ├── JsonTypeResolver.cs
│ ├── Microsoft.Crank.RegressionBot.csproj
│ ├── Models
│ ├── BenchmarksResult.cs
│ ├── DependencyChange.cs
│ ├── Regression.cs
│ └── Report.cs
│ ├── Probe.cs
│ ├── Program.cs
│ ├── Queries.cs
│ ├── RegressionBotException.cs
│ ├── Rule.cs
│ ├── Source.cs
│ ├── SourceSection.cs
│ ├── regressionbot.schema.json
│ ├── sample.config.json
│ └── sample.config.yml
└── test
├── Microsoft.Crank.IntegrationTests
├── AgentFixture.cs
├── AzureWorkerTests.cs
├── CommonTests.cs
├── GitIgnoreTests.cs
├── Microsoft.Crank.IntegrationTests.csproj
├── SkipOnLinuxAttribute.cs
├── SkipOnMacOsAttribute.cs
├── SkipOnWindowsAttribute.cs
└── assets
│ ├── hello.benchmarks.yml
│ ├── multiclient.benchmarks.yml
│ ├── post.benchmarks.yml
│ ├── precommands.benchmarks.yml
│ └── scripts.benchmarks.yml
└── Microsoft.Crank.RegressionBot.Tests
├── Microsoft.Crank.RegressionBot.Tests.csproj
├── TemplateTests.cs
└── assets
├── regressions1.json
├── regressions2.json
├── template1.fluid
└── template2.fluid
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git*
2 | .dockerignore
3 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome:http://EditorConfig.org
2 |
3 | # top-most EditorConfig file
4 | root = true
5 |
6 | # Don't use tabs for indentation.
7 | [*]
8 | indent_style = space
9 | # (Please don't specify an indent_size here; that has too many unintended consequences.)
10 |
11 | # Code files
12 | [*.{cs,csx,vb,vbx}]
13 | indent_size = 4
14 |
15 | # Xml project files
16 | [*.{csproj,vbproj,vcxproj,vcxproj.filters,proj,projitems,shproj,xml}]
17 | indent_size = 2
18 |
19 | # Xml config files
20 | [*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct}]
21 | indent_size = 2
22 |
23 | # JSON files
24 | [*.json]
25 | indent_size = 2
26 |
27 | # Dotnet code style settings:
28 | [*.cs]
29 | # Sort using and Import directives with System.* appearing first
30 | dotnet_sort_system_directives_first = true
31 |
32 | # Don't use this. qualifier
33 | dotnet_style_qualification_for_field = false:suggestion
34 | dotnet_style_qualification_for_property = false:suggestion
35 |
36 | # use int x = .. over Int32
37 | dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
38 |
39 | # use int.MaxValue over Int32.MaxValue
40 | dotnet_style_predefined_type_for_member_access = true:suggestion
41 |
42 | # Require var all the time.
43 | csharp_style_var_for_built_in_types = true:suggestion
44 | csharp_style_var_when_type_is_apparent = true:suggestion
45 | csharp_style_var_elsewhere = true:suggestion
46 |
47 | # Disallow throw expressions.
48 | csharp_style_throw_expression = false:suggestion
49 |
50 | # Newline settings
51 | csharp_new_line_before_open_brace = all
52 | csharp_new_line_before_else = true
53 | csharp_new_line_before_catch = true
54 | csharp_new_line_before_finally = true
55 | csharp_new_line_before_members_in_object_initializers = true
56 | csharp_new_line_before_members_in_anonymous_types = true
57 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.doc diff=astextplain
2 | *.DOC diff=astextplain
3 | *.docx diff=astextplain
4 | *.DOCX diff=astextplain
5 | *.dot diff=astextplain
6 | *.DOT diff=astextplain
7 | *.pdf diff=astextplain
8 | *.PDF diff=astextplain
9 | *.rtf diff=astextplain
10 | *.RTF diff=astextplain
11 |
12 | *.jpg binary
13 | *.png binary
14 | *.gif binary
15 |
16 | *.cs text=auto diff=csharp
17 | *.vb text=auto
18 | *.resx text=auto
19 | *.c text=auto
20 | *.cpp text=auto
21 | *.cxx text=auto
22 | *.h text=auto
23 | *.hxx text=auto
24 | *.py text=auto
25 | *.rb text=auto
26 | *.java text=auto
27 | *.html text=auto
28 | *.htm text=auto
29 | *.css text=auto
30 | *.scss text=auto
31 | *.sass text=auto
32 | *.less text=auto
33 | *.js text=auto
34 | *.lisp text=auto
35 | *.clj text=auto
36 | *.sql text=auto
37 | *.php text=auto
38 | *.lua text=auto
39 | *.m text=auto
40 | *.asm text=auto
41 | *.erl text=auto
42 | *.fs text=auto
43 | *.fsx text=auto
44 | *.hs text=auto
45 |
46 | *.csproj text=auto
47 | *.vbproj text=auto
48 | *.fsproj text=auto
49 | *.dbproj text=auto
50 | *.sln text=auto eol=crlf
51 | *.sh eol=lf
--------------------------------------------------------------------------------
/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 |
8 |
9 | MIT
10 | Microsoft
11 |
12 |
13 |
14 |
15 |
16 | Microsoft Crank
17 | https://github.com/dotnet/crank
18 | git
19 | $(MSBuildThisFileDirectory)
20 |
21 | false
22 |
23 |
24 | false
25 |
26 |
27 | $(NoWarn);8002
28 | latest
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/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 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/build.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | powershell -ExecutionPolicy ByPass -NoProfile -command "& """%~dp0eng\common\Build.ps1""" -restore -build %*"
3 | exit /b %ErrorLevel%
4 |
--------------------------------------------------------------------------------
/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 | "$scriptroot/eng/common/build.sh" --build --restore $@
17 |
--------------------------------------------------------------------------------
/docker/agent/build.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | cpuname=$(uname -p)
4 | docker build -t crank-agent --build-arg CPUNAME=$cpuname -f Dockerfile ../../
--------------------------------------------------------------------------------
/docker/agent/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | url="http://*:5001"
4 | name="crank-agent"
5 | others=""
6 | dockerargs=""
7 |
8 | while [ $# -ne 0 ]
9 | do
10 | case "$1" in
11 | --url)
12 | shift
13 | url="$1"
14 | shift
15 | ;;
16 | --name)
17 | shift
18 | name="$1"
19 | shift
20 | ;;
21 | *)
22 | others+=" $1"
23 | shift
24 | ;;
25 | esac
26 | done
27 |
28 | if [ -n "CRANK_AGENT_AZURE_RELAY_CERT_CLIENT_ID" ]
29 | then
30 | dockerargs+=" --env CRANK_AGENT_AZURE_RELAY_CERT_CLIENT_ID"
31 | fi
32 |
33 | if [ -n "CRANK_AGENT_AZURE_RELAY_CERT_TENANT_ID" ]
34 | then
35 | dockerargs+=" --env CRANK_AGENT_AZURE_RELAY_CERT_TENANT_ID"
36 | fi
37 |
38 | if [ -n "CRANK_AGENT_AZURE_RELAY_CERT_PATH" ]
39 | then
40 | dockerargs+=" -v $CRANK_AGENT_AZURE_RELAY_CERT_PATH:/certs/relay.pfx --env CRANK_AGENT_AZURE_RELAY_CERT_PATH=/certs/relay.pfx"
41 | fi
42 |
43 | # cgroupfs is mapped to allow docker to create cgroups without permissions issues (cgroup v2)
44 | # docker.sock is mapped to be able to manage other docker instances from this one
45 | docker run -it --name $name -d --network host --restart always \
46 | --log-opt max-size=1G --privileged \
47 | -v /sys/fs/cgroup/:/sys/fs/cgroup/ \
48 | -v /var/run/docker.sock:/var/run/docker.sock $dockerargs \
49 | crank-agent \
50 | --url $url $others
51 |
--------------------------------------------------------------------------------
/docker/agent/stop.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | NAME="$1"
4 | shift
5 |
6 | if [ -z "$NAME" ]
7 | then
8 | NAME="crank-agent"
9 | fi
10 |
11 | docker stop "$NAME"
12 | docker rm "$NAME"
13 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 | # 📖 Microsoft.Crank documentation
2 |
3 | ## Tutorials
4 |
5 | | Topic | Description |
6 | |-------|-------------|
7 | |**[Getting Started](getting_started.md)** | Writing your first benchmark.
8 | |**[Benchmarking local applications](local_application.md)** | Send local application source to the agent.
9 | |**[Benchmarking Docker containers](benchmarking_docker.md)** | Run Docker containers.
10 | |**[Running micro-benchmarks](microbenchmarks.md)** | Run BenchmarkDotNet benchmarks.
11 | |**[Setting up an agent on Linux](setup_linux.md)** | How to install and update the agent on a Linux machine.
12 |
13 | ## Guides
14 |
15 | | Topic | Description|
16 | |-------|------------|
17 | |**[Storing results](storing_results.md)** | Storing results locally or in a SQL Server database.
18 | |**[Using different .NET versions](dotnet_versions.md)** | Benchmarking with different .NET versions.
19 | |**[Collecting event counters](event_counters.md)** | Collecting predefined and custom event counters.
20 | |**[Post-processing results](post_processing.md)** | Adding custom results and running scripts.
21 | |**[Running pre-commands](precommands.md)** | Running commands before the job is pushed to the agent.
22 | |**[Reporting custom measurements](measurements.md)** | How to push custom measurement from a job.
23 |
24 |
25 | ## Reference documentation
26 |
27 | | Area | Description |
28 | |------|-------------|
29 | |**[crank command line reference](../src/Microsoft.Crank.Controller/README.md)** | Documentation for `crank` commands.
30 | |**[`benchmarks.yaml` Schema](../src/Microsoft.Crank.Controller/benchmarks.schema.json)** | `benchmarks.yaml` configuration.
31 | |**[Architecture](reference/architecture.md)** | Architecture of Microsoft Crank
32 |
--------------------------------------------------------------------------------
/docs/development.md:
--------------------------------------------------------------------------------
1 | ## Running from source
2 |
3 | Crank can be started from its source code by executing these commands:
4 |
5 | ### Crank Agent
6 |
7 | ```
8 | cd ./src/Microsoft.Crank.Agent
9 | dotnet run
10 | ```
11 |
12 | ### Crank Controller
13 |
14 | ```
15 | cd ./src/Microsoft.Crank.Controller
16 | dotnet run --config ../../samples/hello/hello.benchmarks.yml --scenario hello --profile local
17 | ```
18 |
--------------------------------------------------------------------------------
/docs/reference/architecture.md:
--------------------------------------------------------------------------------
1 | # Architecture
2 |
3 | The benchmarking infrastructure is a simple client-server design. The benchmark controller orchestrates jobs across one or more agents and polls for status.
4 |
5 | The agent runs on each machine that wants to execute jobs and has exposes a simple CRUD HTTP API that can be used to manage the queue of jobs. The job queue on the agent side executes jobs serially.
6 |
7 | See the [diagram](#diagram) for more details.
8 |
9 | ## Jobs, Scenarios, and Profiles
10 |
11 | Jobs are individual units of execution. A job can be encapsulated by a Dockerfile, or a .NET project. Scenarios are a list of jobs that the controller will orchestrate.
12 |
13 | ```yaml
14 | imports:
15 | - https://raw.githubusercontent.com/dotnet/crank/main/src/Microsoft.Crank.Jobs.Bombardier/bombardier.yml
16 |
17 | jobs:
18 | server:
19 | sources:
20 | crank:
21 | repository: https://github.com/dotnet/crank
22 | branchOrCommit: main
23 | project: crank/samples/hello/hello.csproj
24 |
25 | scenarios:
26 | hello:
27 | application:
28 | job: server
29 | load:
30 | job: bombardier
31 | variables:
32 | serverPort: 5000
33 | path: /
34 | ```
35 |
36 | In the above manifest, there are 2 jobs defined:
37 | 1. The "server" job
38 | 2. The "bombardier" job (defined in the imports section)
39 |
40 | The server job runs a hello world ASP.NET Core application and the bombardier job is a benchmarking tools with specific variables defined to exert load on the server job. We specify a variable called serverPort to tell the client what port to hit on the server job.
41 |
42 | ## Diagram
43 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/docs/setup_linux.md:
--------------------------------------------------------------------------------
1 | ## Setting up an agent on Linux
2 |
3 | On Linux, it is recommended to setup the Agent using the Docker file provided in this repository.
4 | There instructions are valid for x86_64 and ARM64 (aka ARMv8 or AARCH64).
5 |
6 | ### Installing Docker
7 |
8 | - Install docker from the automated script
9 |
10 | ```
11 | curl -sSL https://get.docker.com | sh
12 | ```
13 |
14 | - Add the local account to the docker user group so that you can execute docker commands without sudo
15 |
16 | ```
17 | sudo groupadd docker
18 | sudo usermod -aG docker $USER
19 | newgrp docker
20 | ```
21 |
22 | - Reopen the session with the account
23 | - Check Docker is running
24 |
25 | ```
26 | docker run hello-world
27 | ```
28 |
29 | ### Starting the Agent
30 |
31 | - Clone the `crank` repository
32 |
33 | ```
34 | mkdir ~/src
35 | cd ~/src
36 | git clone https://github.com/dotnet/crank
37 | ```
38 |
39 | - Build and run the Agent docker image
40 |
41 | ```
42 | cd ~/src/crank/docker/agent
43 | ./build.sh
44 | ./run.sh
45 | ```
46 |
47 | This will build the image with all the dependencies (perfcollect, ...) and start a container named `crank-agent`.
48 | To stop the container, run `./stop.sh`
49 |
50 | ### Displaying the agent log
51 |
52 | To display the live log, run the following command:
53 |
54 | ```
55 | docker logs -f --tail 100 crank-agent
56 | ```
57 |
58 | ### Continuous integration
59 |
60 | In order to restart and update the agent regularly, the following cron job can be used.
61 |
62 | - Edit the crontab file:
63 |
64 | ```
65 | crontab -e
66 | ```
67 |
68 | - Add this entry:
69 |
70 | ```
71 | 0 0 * * * cd [PATH_TO_CRANK]/src/crank/docker/agent; ./stop.sh; docker rm -f $(docker ps -a -q --filter "label=benchmarks"); docker system prune --all --force --volumes; git checkout -f master; git pull; ./build.sh; ./run.sh
72 | ```
73 |
74 | This will stop any running agent, clean all docker images used to run benchmarks, update the GitHub repositor, build and restart the agent image.
75 |
--------------------------------------------------------------------------------
/eng/Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/eng/PoliCheckExclusions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/eng/Publishing.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 3
5 |
6 |
7 |
--------------------------------------------------------------------------------
/eng/Version.Details.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | https://github.com/dotnet/arcade
8 | 4246a31e5de9de87f760218c4f588cebf4661f45
9 |
10 |
11 | https://github.com/dotnet/arcade
12 | 4246a31e5de9de87f760218c4f588cebf4661f45
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/eng/Versions.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 0.2.0
5 | alpha
6 |
7 |
8 |
--------------------------------------------------------------------------------
/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 %*"
--------------------------------------------------------------------------------
/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/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 $@
--------------------------------------------------------------------------------
/eng/common/cross/arm/sources.list.bionic:
--------------------------------------------------------------------------------
1 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe
2 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe
3 |
4 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe
5 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe
6 |
7 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted
8 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted
9 |
10 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse
11 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse
12 |
--------------------------------------------------------------------------------
/eng/common/cross/arm/sources.list.focal:
--------------------------------------------------------------------------------
1 | deb http://ports.ubuntu.com/ubuntu-ports/ focal main restricted universe
2 | deb-src http://ports.ubuntu.com/ubuntu-ports/ focal main restricted universe
3 |
4 | deb http://ports.ubuntu.com/ubuntu-ports/ focal-updates main restricted universe
5 | deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-updates main restricted universe
6 |
7 | deb http://ports.ubuntu.com/ubuntu-ports/ focal-backports main restricted
8 | deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-backports main restricted
9 |
10 | deb http://ports.ubuntu.com/ubuntu-ports/ focal-security main restricted universe multiverse
11 | deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-security main restricted universe multiverse
12 |
--------------------------------------------------------------------------------
/eng/common/cross/arm/sources.list.jammy:
--------------------------------------------------------------------------------
1 | deb http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe
2 | deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe
3 |
4 | deb http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe
5 | deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe
6 |
7 | deb http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted
8 | deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted
9 |
10 | deb http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse
11 | deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse
12 |
--------------------------------------------------------------------------------
/eng/common/cross/arm/sources.list.jessie:
--------------------------------------------------------------------------------
1 | # Debian (sid) # UNSTABLE
2 | deb http://ftp.debian.org/debian/ sid main contrib non-free
3 | deb-src http://ftp.debian.org/debian/ sid main contrib non-free
4 |
--------------------------------------------------------------------------------
/eng/common/cross/arm/sources.list.xenial:
--------------------------------------------------------------------------------
1 | deb http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe
2 | deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe
3 |
4 | deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe
5 | deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe
6 |
7 | deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
8 | deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
9 |
10 | deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse
11 | deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse
12 |
--------------------------------------------------------------------------------
/eng/common/cross/arm/sources.list.zesty:
--------------------------------------------------------------------------------
1 | deb http://ports.ubuntu.com/ubuntu-ports/ zesty main restricted universe
2 | deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty main restricted universe
3 |
4 | deb http://ports.ubuntu.com/ubuntu-ports/ zesty-updates main restricted universe
5 | deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty-updates main restricted universe
6 |
7 | deb http://ports.ubuntu.com/ubuntu-ports/ zesty-backports main restricted
8 | deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty-backports main restricted
9 |
10 | deb http://ports.ubuntu.com/ubuntu-ports/ zesty-security main restricted universe multiverse
11 | deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty-security main restricted universe multiverse
12 |
--------------------------------------------------------------------------------
/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/sources.list.bionic:
--------------------------------------------------------------------------------
1 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe
2 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe
3 |
4 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe
5 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe
6 |
7 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted
8 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted
9 |
10 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse
11 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse
12 |
--------------------------------------------------------------------------------
/eng/common/cross/arm64/sources.list.buster:
--------------------------------------------------------------------------------
1 | deb http://deb.debian.org/debian buster main
2 | deb-src http://deb.debian.org/debian buster main
3 |
4 | deb http://deb.debian.org/debian-security/ buster/updates main
5 | deb-src http://deb.debian.org/debian-security/ buster/updates main
6 |
7 | deb http://deb.debian.org/debian buster-updates main
8 | deb-src http://deb.debian.org/debian buster-updates main
9 |
10 | deb http://deb.debian.org/debian buster-backports main contrib non-free
11 | deb-src http://deb.debian.org/debian buster-backports main contrib non-free
12 |
--------------------------------------------------------------------------------
/eng/common/cross/arm64/sources.list.focal:
--------------------------------------------------------------------------------
1 | deb http://ports.ubuntu.com/ubuntu-ports/ focal main restricted universe
2 | deb-src http://ports.ubuntu.com/ubuntu-ports/ focal main restricted universe
3 |
4 | deb http://ports.ubuntu.com/ubuntu-ports/ focal-updates main restricted universe
5 | deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-updates main restricted universe
6 |
7 | deb http://ports.ubuntu.com/ubuntu-ports/ focal-backports main restricted
8 | deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-backports main restricted
9 |
10 | deb http://ports.ubuntu.com/ubuntu-ports/ focal-security main restricted universe multiverse
11 | deb-src http://ports.ubuntu.com/ubuntu-ports/ focal-security main restricted universe multiverse
12 |
--------------------------------------------------------------------------------
/eng/common/cross/arm64/sources.list.jammy:
--------------------------------------------------------------------------------
1 | deb http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe
2 | deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy main restricted universe
3 |
4 | deb http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe
5 | deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-updates main restricted universe
6 |
7 | deb http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted
8 | deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-backports main restricted
9 |
10 | deb http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse
11 | deb-src http://ports.ubuntu.com/ubuntu-ports/ jammy-security main restricted universe multiverse
12 |
--------------------------------------------------------------------------------
/eng/common/cross/arm64/sources.list.stretch:
--------------------------------------------------------------------------------
1 | deb http://deb.debian.org/debian stretch main
2 | deb-src http://deb.debian.org/debian stretch main
3 |
4 | deb http://deb.debian.org/debian-security/ stretch/updates main
5 | deb-src http://deb.debian.org/debian-security/ stretch/updates main
6 |
7 | deb http://deb.debian.org/debian stretch-updates main
8 | deb-src http://deb.debian.org/debian stretch-updates main
9 |
10 | deb http://deb.debian.org/debian stretch-backports main contrib non-free
11 | deb-src http://deb.debian.org/debian stretch-backports main contrib non-free
12 |
13 |
--------------------------------------------------------------------------------
/eng/common/cross/arm64/sources.list.xenial:
--------------------------------------------------------------------------------
1 | deb http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe
2 | deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial main restricted universe
3 |
4 | deb http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe
5 | deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-updates main restricted universe
6 |
7 | deb http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
8 | deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-backports main restricted
9 |
10 | deb http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse
11 | deb-src http://ports.ubuntu.com/ubuntu-ports/ xenial-security main restricted universe multiverse
12 |
--------------------------------------------------------------------------------
/eng/common/cross/arm64/sources.list.zesty:
--------------------------------------------------------------------------------
1 | deb http://ports.ubuntu.com/ubuntu-ports/ zesty main restricted universe
2 | deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty main restricted universe
3 |
4 | deb http://ports.ubuntu.com/ubuntu-ports/ zesty-updates main restricted universe
5 | deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty-updates main restricted universe
6 |
7 | deb http://ports.ubuntu.com/ubuntu-ports/ zesty-backports main restricted
8 | deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty-backports main restricted
9 |
10 | deb http://ports.ubuntu.com/ubuntu-ports/ zesty-security main restricted universe multiverse
11 | deb-src http://ports.ubuntu.com/ubuntu-ports/ zesty-security main restricted universe multiverse
12 |
--------------------------------------------------------------------------------
/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 ( /lib/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/armel.jessie.patch:
--------------------------------------------------------------------------------
1 | diff -u -r a/usr/include/urcu/uatomic/generic.h b/usr/include/urcu/uatomic/generic.h
2 | --- a/usr/include/urcu/uatomic/generic.h 2014-10-22 15:00:58.000000000 -0700
3 | +++ b/usr/include/urcu/uatomic/generic.h 2020-10-30 21:38:28.550000000 -0700
4 | @@ -69,10 +69,10 @@
5 | #endif
6 | #ifdef UATOMIC_HAS_ATOMIC_SHORT
7 | case 2:
8 | - return __sync_val_compare_and_swap_2(addr, old, _new);
9 | + return __sync_val_compare_and_swap_2((uint16_t*) addr, old, _new);
10 | #endif
11 | case 4:
12 | - return __sync_val_compare_and_swap_4(addr, old, _new);
13 | + return __sync_val_compare_and_swap_4((uint32_t*) addr, old, _new);
14 | #if (CAA_BITS_PER_LONG == 64)
15 | case 8:
16 | return __sync_val_compare_and_swap_8(addr, old, _new);
17 | @@ -109,7 +109,7 @@
18 | return;
19 | #endif
20 | case 4:
21 | - __sync_and_and_fetch_4(addr, val);
22 | + __sync_and_and_fetch_4((uint32_t*) addr, val);
23 | return;
24 | #if (CAA_BITS_PER_LONG == 64)
25 | case 8:
26 | @@ -148,7 +148,7 @@
27 | return;
28 | #endif
29 | case 4:
30 | - __sync_or_and_fetch_4(addr, val);
31 | + __sync_or_and_fetch_4((uint32_t*) addr, val);
32 | return;
33 | #if (CAA_BITS_PER_LONG == 64)
34 | case 8:
35 | @@ -187,7 +187,7 @@
36 | return __sync_add_and_fetch_2(addr, val);
37 | #endif
38 | case 4:
39 | - return __sync_add_and_fetch_4(addr, val);
40 | + return __sync_add_and_fetch_4((uint32_t*) addr, val);
41 | #if (CAA_BITS_PER_LONG == 64)
42 | case 8:
43 | return __sync_add_and_fetch_8(addr, val);
44 |
--------------------------------------------------------------------------------
/eng/common/cross/armel/sources.list.jessie:
--------------------------------------------------------------------------------
1 | # Debian (jessie) # Stable
2 | deb http://ftp.debian.org/debian/ jessie main contrib non-free
3 | deb-src http://ftp.debian.org/debian/ jessie main contrib non-free
4 |
--------------------------------------------------------------------------------
/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/armv6/sources.list.buster:
--------------------------------------------------------------------------------
1 | deb http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi
2 | deb-src http://raspbian.raspberrypi.org/raspbian/ buster main contrib non-free rpi
3 |
--------------------------------------------------------------------------------
/eng/common/cross/ppc64le/sources.list.bionic:
--------------------------------------------------------------------------------
1 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe
2 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe
3 |
4 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe
5 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe
6 |
7 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted
8 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted
9 |
10 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse
11 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse
12 |
--------------------------------------------------------------------------------
/eng/common/cross/riscv64/sources.list.sid:
--------------------------------------------------------------------------------
1 | deb http://deb.debian.org/debian-ports sid main
2 |
--------------------------------------------------------------------------------
/eng/common/cross/s390x/sources.list.bionic:
--------------------------------------------------------------------------------
1 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe
2 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic main restricted universe
3 |
4 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe
5 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-updates main restricted universe
6 |
7 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted
8 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-backports main restricted
9 |
10 | deb http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse
11 | deb-src http://ports.ubuntu.com/ubuntu-ports/ bionic-security main restricted universe multiverse
12 |
--------------------------------------------------------------------------------
/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 | *)
26 | echo "Unsupported architecture for tizen: $ARCH"
27 | exit 1
28 | esac
29 |
30 | __CrossDir=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
31 | __TIZEN_CROSSDIR="$__CrossDir/${ARCH}/tizen"
32 |
33 | if [[ -z "$ROOTFS_DIR" ]]; then
34 | echo "ROOTFS_DIR is not defined."
35 | exit 1;
36 | fi
37 |
38 | TIZEN_TMP_DIR=$ROOTFS_DIR/tizen_tmp
39 | mkdir -p $TIZEN_TMP_DIR
40 |
41 | # Download files
42 | echo ">>Start downloading files"
43 | VERBOSE=1 $__CrossDir/tizen-fetch.sh $TIZEN_TMP_DIR $TIZEN_ARCH
44 | echo "<>Start constructing Tizen rootfs"
47 | TIZEN_RPM_FILES=`ls $TIZEN_TMP_DIR/*.rpm`
48 | cd $ROOTFS_DIR
49 | for f in $TIZEN_RPM_FILES; do
50 | rpm2cpio $f | cpio -idm --quiet
51 | done
52 | echo "<>Start configuring Tizen rootfs"
59 | ln -sfn asm-${LINK_ARCH} ./usr/include/asm
60 | patch -p1 < $__TIZEN_CROSSDIR/tizen.patch
61 | echo "<\\|?@*"() ]', '_'
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 | # replace all special characters with _, some builds use special characters like : in Agent.Jobname, that is not a permissible name while uploading artifacts.
18 | artifact_name=$SYSTEM_STAGENAME"_"$AGENT_JOBNAME"_SBOM"
19 | safe_artifact_name="${artifact_name//["/:<>\\|?@*$" ]/_}"
20 |
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 | msbuild
5 |
6 |
7 |
8 |
9 | %(Identity)
10 |
11 |
12 |
13 |
14 |
15 | $(WorkItemDirectory)
16 | $(WorkItemCommand)
17 | $(WorkItemTimeout)
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/eng/common/internal/NuGet.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/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 | #!/usr/bin/env bash
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 | ;;
39 |
40 | loongarch64)
41 | arch=loongarch64
42 | ;;
43 |
44 | riscv64)
45 | arch=riscv64
46 | ;;
47 |
48 | amd64|x86_64)
49 | arch=x64
50 | ;;
51 |
52 | armv7l|armv8l)
53 | if (NAME=""; . /etc/os-release; test "$NAME" = "Tizen"); then
54 | arch=armel
55 | else
56 | arch=arm
57 | fi
58 | ;;
59 |
60 | armv6l)
61 | arch=armv6
62 | ;;
63 |
64 | i[3-6]86)
65 | echo "Unsupported CPU $CPUName detected, build might not succeed!"
66 | arch=x86
67 | ;;
68 |
69 | s390x)
70 | arch=s390x
71 | ;;
72 |
73 | ppc64le)
74 | arch=ppc64le
75 | ;;
76 | *)
77 | echo "Unknown CPU $CPUName detected!"
78 | exit 1
79 | ;;
80 | esac
81 |
--------------------------------------------------------------------------------
/eng/common/post-build/add-build-to-channel.ps1:
--------------------------------------------------------------------------------
1 | param(
2 | [Parameter(Mandatory=$true)][int] $BuildId,
3 | [Parameter(Mandatory=$true)][int] $ChannelId,
4 | [Parameter(Mandatory=$true)][string] $MaestroApiAccessToken,
5 | [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro.dot.net',
6 | [Parameter(Mandatory=$false)][string] $MaestroApiVersion = '2019-01-16'
7 | )
8 |
9 | try {
10 | . $PSScriptRoot\post-build-utils.ps1
11 |
12 | # Check that the channel we are going to promote the build to exist
13 | $channelInfo = Get-MaestroChannel -ChannelId $ChannelId
14 |
15 | if (!$channelInfo) {
16 | Write-PipelineTelemetryCategory -Category 'PromoteBuild' -Message "Channel with BAR ID $ChannelId was not found in BAR!"
17 | ExitWithExitCode 1
18 | }
19 |
20 | # Get info about which channel(s) the build has already been promoted to
21 | $buildInfo = Get-MaestroBuild -BuildId $BuildId
22 |
23 | if (!$buildInfo) {
24 | Write-PipelineTelemetryError -Category 'PromoteBuild' -Message "Build with BAR ID $BuildId was not found in BAR!"
25 | ExitWithExitCode 1
26 | }
27 |
28 | # Find whether the build is already assigned to the channel or not
29 | if ($buildInfo.channels) {
30 | foreach ($channel in $buildInfo.channels) {
31 | if ($channel.Id -eq $ChannelId) {
32 | Write-Host "The build with BAR ID $BuildId is already on channel $ChannelId!"
33 | ExitWithExitCode 0
34 | }
35 | }
36 | }
37 |
38 | Write-Host "Promoting build '$BuildId' to channel '$ChannelId'."
39 |
40 | Assign-BuildToChannel -BuildId $BuildId -ChannelId $ChannelId
41 |
42 | Write-Host 'done.'
43 | }
44 | catch {
45 | Write-Host $_
46 | Write-PipelineTelemetryError -Category 'PromoteBuild' -Message "There was an error while trying to promote build '$BuildId' to channel '$ChannelId'"
47 | ExitWithExitCode 1
48 | }
49 |
--------------------------------------------------------------------------------
/eng/common/post-build/check-channel-consistency.ps1:
--------------------------------------------------------------------------------
1 | param(
2 | [Parameter(Mandatory=$true)][string] $PromoteToChannels, # List of channels that the build should be promoted to
3 | [Parameter(Mandatory=$true)][array] $AvailableChannelIds # List of channel IDs available in the YAML implementation
4 | )
5 |
6 | try {
7 | . $PSScriptRoot\post-build-utils.ps1
8 |
9 | if ($PromoteToChannels -eq "") {
10 | Write-PipelineTaskError -Type 'warning' -Message "This build won't publish assets as it's not configured to any Maestro channel. If that wasn't intended use Darc to configure a default channel using add-default-channel for this branch or to promote it to a channel using add-build-to-channel. See https://github.com/dotnet/arcade/blob/master/Documentation/Darc.md#assigning-an-individual-build-to-a-channel for more info."
11 | ExitWithExitCode 0
12 | }
13 |
14 | # Check that every channel that Maestro told to promote the build to
15 | # is available in YAML
16 | $PromoteToChannelsIds = $PromoteToChannels -split "\D" | Where-Object { $_ }
17 |
18 | $hasErrors = $false
19 |
20 | foreach ($id in $PromoteToChannelsIds) {
21 | if (($id -ne 0) -and ($id -notin $AvailableChannelIds)) {
22 | Write-PipelineTaskError -Message "Channel $id is not present in the post-build YAML configuration! This is an error scenario. Please contact @dnceng."
23 | $hasErrors = $true
24 | }
25 | }
26 |
27 | # The `Write-PipelineTaskError` doesn't error the script and we might report several errors
28 | # in the previous lines. The check below makes sure that we return an error state from the
29 | # script if we reported any validation error
30 | if ($hasErrors) {
31 | ExitWithExitCode 1
32 | }
33 |
34 | Write-Host 'done.'
35 | }
36 | catch {
37 | Write-Host $_
38 | Write-PipelineTelemetryError -Category 'CheckChannelConsistency' -Message "There was an error while trying to check consistency of Maestro default channels for the build and post-build YAML configuration."
39 | ExitWithExitCode 1
40 | }
41 |
--------------------------------------------------------------------------------
/eng/common/post-build/nuget-validation.ps1:
--------------------------------------------------------------------------------
1 | # This script validates NuGet package metadata information using this
2 | # tool: https://github.com/NuGet/NuGetGallery/tree/jver-verify/src/VerifyMicrosoftPackage
3 |
4 | param(
5 | [Parameter(Mandatory=$true)][string] $PackagesPath, # Path to where the packages to be validated are
6 | [Parameter(Mandatory=$true)][string] $ToolDestinationPath # Where the validation tool should be downloaded to
7 | )
8 |
9 | try {
10 | . $PSScriptRoot\post-build-utils.ps1
11 |
12 | $url = 'https://raw.githubusercontent.com/NuGet/NuGetGallery/3e25ad135146676bcab0050a516939d9958bfa5d/src/VerifyMicrosoftPackage/verify.ps1'
13 |
14 | New-Item -ItemType 'directory' -Path ${ToolDestinationPath} -Force
15 |
16 | Invoke-WebRequest $url -OutFile ${ToolDestinationPath}\verify.ps1
17 |
18 | & ${ToolDestinationPath}\verify.ps1 ${PackagesPath}\*.nupkg
19 | }
20 | catch {
21 | Write-Host $_.ScriptStackTrace
22 | Write-PipelineTelemetryError -Category 'NuGetValidation' -Message $_
23 | ExitWithExitCode 1
24 | }
25 |
--------------------------------------------------------------------------------
/eng/common/post-build/publish-using-darc.ps1:
--------------------------------------------------------------------------------
1 | param(
2 | [Parameter(Mandatory=$true)][int] $BuildId,
3 | [Parameter(Mandatory=$true)][int] $PublishingInfraVersion,
4 | [Parameter(Mandatory=$true)][string] $AzdoToken,
5 | [Parameter(Mandatory=$false)][string] $MaestroApiEndPoint = 'https://maestro.dot.net',
6 | [Parameter(Mandatory=$true)][string] $WaitPublishingFinish,
7 | [Parameter(Mandatory=$false)][string] $ArtifactsPublishingAdditionalParameters,
8 | [Parameter(Mandatory=$false)][string] $SymbolPublishingAdditionalParameters
9 | )
10 |
11 | try {
12 | . $PSScriptRoot\post-build-utils.ps1
13 |
14 | $darc = Get-Darc
15 |
16 | $optionalParams = [System.Collections.ArrayList]::new()
17 |
18 | if ("" -ne $ArtifactsPublishingAdditionalParameters) {
19 | $optionalParams.Add("--artifact-publishing-parameters") | Out-Null
20 | $optionalParams.Add($ArtifactsPublishingAdditionalParameters) | Out-Null
21 | }
22 |
23 | if ("" -ne $SymbolPublishingAdditionalParameters) {
24 | $optionalParams.Add("--symbol-publishing-parameters") | Out-Null
25 | $optionalParams.Add($SymbolPublishingAdditionalParameters) | Out-Null
26 | }
27 |
28 | if ("false" -eq $WaitPublishingFinish) {
29 | $optionalParams.Add("--no-wait") | Out-Null
30 | }
31 |
32 | & $darc add-build-to-channel `
33 | --id $buildId `
34 | --publishing-infra-version $PublishingInfraVersion `
35 | --default-channels `
36 | --source-branch main `
37 | --azdev-pat "$AzdoToken" `
38 | --bar-uri "$MaestroApiEndPoint" `
39 | --ci `
40 | @optionalParams
41 |
42 | if ($LastExitCode -ne 0) {
43 | Write-Host "Problems using Darc to promote build ${buildId} to default channels. Stopping execution..."
44 | exit 1
45 | }
46 |
47 | Write-Host 'done.'
48 | }
49 | catch {
50 | Write-Host $_
51 | Write-PipelineTelemetryError -Category 'PromoteBuild' -Message "There was an error while trying to publish build '$BuildId' to default channels."
52 | ExitWithExitCode 1
53 | }
54 |
--------------------------------------------------------------------------------
/eng/common/retain-build.ps1:
--------------------------------------------------------------------------------
1 |
2 | Param(
3 | [Parameter(Mandatory=$true)][int] $buildId,
4 | [Parameter(Mandatory=$true)][string] $azdoOrgUri,
5 | [Parameter(Mandatory=$true)][string] $azdoProject,
6 | [Parameter(Mandatory=$true)][string] $token
7 | )
8 |
9 | $ErrorActionPreference = 'Stop'
10 | Set-StrictMode -Version 2.0
11 |
12 | function Get-AzDOHeaders(
13 | [string] $token)
14 | {
15 | $base64AuthInfo = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(":${token}"))
16 | $headers = @{"Authorization"="Basic $base64AuthInfo"}
17 | return $headers
18 | }
19 |
20 | function Update-BuildRetention(
21 | [string] $azdoOrgUri,
22 | [string] $azdoProject,
23 | [int] $buildId,
24 | [string] $token)
25 | {
26 | $headers = Get-AzDOHeaders -token $token
27 | $requestBody = "{
28 | `"keepForever`": `"true`"
29 | }"
30 |
31 | $requestUri = "${azdoOrgUri}/${azdoProject}/_apis/build/builds/${buildId}?api-version=6.0"
32 | write-Host "Attempting to retain build using the following URI: ${requestUri} ..."
33 |
34 | try {
35 | Invoke-RestMethod -Uri $requestUri -Method Patch -Body $requestBody -Header $headers -contentType "application/json"
36 | Write-Host "Updated retention settings for build ${buildId}."
37 | }
38 | catch {
39 | Write-Error "Failed to update retention settings for build: $_.Exception.Response.StatusDescription"
40 | exit 1
41 | }
42 | }
43 |
44 | Update-BuildRetention -azdoOrgUri $azdoOrgUri -azdoProject $azdoProject -buildId $buildId -token $token
45 | exit 0
46 |
--------------------------------------------------------------------------------
/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/init-sdl.ps1:
--------------------------------------------------------------------------------
1 | Param(
2 | [string] $GuardianCliLocation,
3 | [string] $Repository,
4 | [string] $BranchName='master',
5 | [string] $WorkingDirectory,
6 | [string] $GuardianLoggerLevel='Standard'
7 | )
8 |
9 | $ErrorActionPreference = 'Stop'
10 | Set-StrictMode -Version 2.0
11 | $disableConfigureToolsetImport = $true
12 | $global:LASTEXITCODE = 0
13 |
14 | # `tools.ps1` checks $ci to perform some actions. Since the SDL
15 | # scripts don't necessarily execute in the same agent that run the
16 | # build.ps1/sh script this variable isn't automatically set.
17 | $ci = $true
18 | . $PSScriptRoot\..\tools.ps1
19 |
20 | # Don't display the console progress UI - it's a huge perf hit
21 | $ProgressPreference = 'SilentlyContinue'
22 |
23 | Add-Type -AssemblyName System.IO.Compression.FileSystem
24 |
25 | try {
26 | # if the folder does not exist, we'll do a guardian init and push it to the remote repository
27 | Write-Host 'Initializing Guardian...'
28 | Write-Host "$GuardianCliLocation init --working-directory $WorkingDirectory --logger-level $GuardianLoggerLevel"
29 | & $GuardianCliLocation init --working-directory $WorkingDirectory --logger-level $GuardianLoggerLevel
30 | if ($LASTEXITCODE -ne 0) {
31 | Write-PipelineTelemetryError -Force -Category 'Build' -Message "Guardian init failed with exit code $LASTEXITCODE."
32 | ExitWithExitCode $LASTEXITCODE
33 | }
34 | # We create the mainbaseline so it can be edited later
35 | Write-Host "$GuardianCliLocation baseline --working-directory $WorkingDirectory --name mainbaseline"
36 | & $GuardianCliLocation baseline --working-directory $WorkingDirectory --name mainbaseline
37 | if ($LASTEXITCODE -ne 0) {
38 | Write-PipelineTelemetryError -Force -Category 'Build' -Message "Guardian baseline failed with exit code $LASTEXITCODE."
39 | ExitWithExitCode $LASTEXITCODE
40 | }
41 | ExitWithExitCode 0
42 | }
43 | catch {
44 | Write-Host $_.ScriptStackTrace
45 | Write-PipelineTelemetryError -Force -Category 'Sdl' -Message $_
46 | ExitWithExitCode 1
47 | }
48 |
--------------------------------------------------------------------------------
/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 | [string]$Source = "https://pkgs.dev.azure.com/dnceng/_packaging/Guardian1ESPTUpstreamOrgFeed/nuget/v3/index.json",
8 |
9 | # If omitted, install the latest version of Guardian, otherwise install that specific version.
10 | [string]$Version
11 | )
12 |
13 | $ErrorActionPreference = 'Stop'
14 | Set-StrictMode -Version 2.0
15 | $disableConfigureToolsetImport = $true
16 | $global:LASTEXITCODE = 0
17 |
18 | # `tools.ps1` checks $ci to perform some actions. Since the SDL
19 | # scripts don't necessarily execute in the same agent that run the
20 | # build.ps1/sh script this variable isn't automatically set.
21 | $ci = $true
22 | . $PSScriptRoot\..\tools.ps1
23 |
24 | $argumentList = @("install", "Microsoft.Guardian.Cli.win-x64", "-Source $Source", "-OutputDirectory $Path", "-NonInteractive", "-NoCache")
25 |
26 | if ($Version) {
27 | $argumentList += "-Version $Version"
28 | }
29 |
30 | Start-Process nuget -Verbose -ArgumentList $argumentList -NoNewWindow -Wait
31 |
32 | $gdnCliPath = Get-ChildItem -Filter guardian.cmd -Recurse -Path $Path
33 |
34 | if (!$gdnCliPath)
35 | {
36 | Write-PipelineTelemetryError -Category 'Sdl' -Message 'Failure installing Guardian'
37 | }
38 |
39 | return $gdnCliPath.FullName
40 | }
--------------------------------------------------------------------------------
/eng/common/templates-official/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 |
9 | jobs:
10 | - template: /eng/common/templates-official/jobs/jobs.yml
11 | parameters:
12 | enableMicrobuild: false
13 | enablePublishBuildArtifacts: false
14 | enablePublishTestResults: false
15 | enablePublishBuildAssets: false
16 | enablePublishUsingPipelines: false
17 | enableTelemetry: true
18 |
19 | variables:
20 | - group: Publish-Build-Assets
21 | # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in
22 | # sync with the packages.config file.
23 | - name: DefaultGuardianVersion
24 | value: 0.109.0
25 | - name: GuardianPackagesConfigFile
26 | value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config
27 | - name: GuardianVersion
28 | value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }}
29 |
30 | jobs: ${{ parameters.jobs }}
31 |
32 |
--------------------------------------------------------------------------------
/eng/common/templates-official/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: MaestroApiAccessToken
12 | value: $(MaestroAccessToken)
13 | - name: MaestroApiVersion
14 | value: "2020-02-20"
15 |
16 | - name: SourceLinkCLIVersion
17 | value: 3.0.0
18 | - name: SymbolToolVersion
19 | value: 1.0.1
20 |
21 | - name: runCodesignValidationInjection
22 | value: false
23 |
--------------------------------------------------------------------------------
/eng/common/templates-official/post-build/trigger-subscription.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | ChannelId: 0
3 |
4 | steps:
5 | - task: PowerShell@2
6 | displayName: Triggering subscriptions
7 | inputs:
8 | filePath: $(Build.SourcesDirectory)/eng/common/post-build/trigger-subscriptions.ps1
9 | arguments: -SourceRepo $(Build.Repository.Uri)
10 | -ChannelId ${{ parameters.ChannelId }}
11 | -MaestroApiAccessToken $(MaestroAccessToken)
12 | -MaestroApiEndPoint $(MaestroApiEndPoint)
13 | -MaestroApiVersion $(MaestroApiVersion)
14 |
--------------------------------------------------------------------------------
/eng/common/templates-official/steps/add-build-to-channel.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | ChannelId: 0
3 |
4 | steps:
5 | - task: PowerShell@2
6 | displayName: Add Build to Channel
7 | inputs:
8 | filePath: $(Build.SourcesDirectory)/eng/common/post-build/add-build-to-channel.ps1
9 | arguments: -BuildId $(BARBuildId)
10 | -ChannelId ${{ parameters.ChannelId }}
11 | -MaestroApiAccessToken $(MaestroApiAccessToken)
12 | -MaestroApiEndPoint $(MaestroApiEndPoint)
13 | -MaestroApiVersion $(MaestroApiVersion)
14 |
--------------------------------------------------------------------------------
/eng/common/templates-official/steps/build-reason.yml:
--------------------------------------------------------------------------------
1 | # build-reason.yml
2 | # Description: runs steps if build.reason condition is valid. conditions is a string of valid build reasons
3 | # to include steps (',' separated).
4 | parameters:
5 | conditions: ''
6 | steps: []
7 |
8 | steps:
9 | - ${{ if and( not(startsWith(parameters.conditions, 'not')), contains(parameters.conditions, variables['build.reason'])) }}:
10 | - ${{ parameters.steps }}
11 | - ${{ if and( startsWith(parameters.conditions, 'not'), not(contains(parameters.conditions, variables['build.reason']))) }}:
12 | - ${{ parameters.steps }}
13 |
--------------------------------------------------------------------------------
/eng/common/templates-official/steps/component-governance.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | disableComponentGovernance: false
3 | componentGovernanceIgnoreDirectories: ''
4 |
5 | steps:
6 | - ${{ if eq(parameters.disableComponentGovernance, 'true') }}:
7 | - script: echo "##vso[task.setvariable variable=skipComponentGovernanceDetection]true"
8 | displayName: Set skipComponentGovernanceDetection variable
9 | - ${{ if ne(parameters.disableComponentGovernance, 'true') }}:
10 | - task: ComponentGovernanceComponentDetection@0
11 | continueOnError: true
12 | inputs:
13 | ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }}
--------------------------------------------------------------------------------
/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 |
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 |
18 | steps:
19 | - ${{ if ne(variables['System.TeamProject'], 'public') }}:
20 | - template: /eng/common/templates-official/steps/get-delegation-sas.yml
21 | parameters:
22 | federatedServiceConnection: ${{ parameters.federatedServiceConnection }}
23 | outputVariableName: ${{ parameters.outputVariableName }}
24 | expiryInHours: ${{ parameters.expiryInHours }}
25 | base64Encode: ${{ parameters.base64Encode }}
26 | storageAccount: dotnetbuilds
27 | container: internal
28 | permissions: rl
29 |
--------------------------------------------------------------------------------
/eng/common/templates-official/steps/get-federated-access-token.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | - name: federatedServiceConnection
3 | type: string
4 | - name: outputVariableName
5 | type: string
6 | - name: stepName
7 | type: string
8 | default: 'getFederatedAccessToken'
9 | - name: condition
10 | type: string
11 | default: ''
12 | # Resource to get a token for. Common values include:
13 | # - '499b84ac-1321-427f-aa17-267ca6975798' for Azure DevOps
14 | # - 'https://storage.azure.com/' for storage
15 | # Defaults to Azure DevOps
16 | - name: resource
17 | type: string
18 | default: '499b84ac-1321-427f-aa17-267ca6975798'
19 | - name: isStepOutputVariable
20 | type: boolean
21 | default: false
22 |
23 | steps:
24 | - task: AzureCLI@2
25 | displayName: 'Getting federated access token for feeds'
26 | name: ${{ parameters.stepName }}
27 | ${{ if ne(parameters.condition, '') }}:
28 | condition: ${{ parameters.condition }}
29 | inputs:
30 | azureSubscription: ${{ parameters.federatedServiceConnection }}
31 | scriptType: 'pscore'
32 | scriptLocation: 'inlineScript'
33 | inlineScript: |
34 | $accessToken = az account get-access-token --query accessToken --resource ${{ parameters.resource }} --output tsv
35 | if ($LASTEXITCODE -ne 0) {
36 | Write-Error "Failed to get access token for resource '${{ parameters.resource }}'"
37 | exit 1
38 | }
39 | Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value"
40 | Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true;isOutput=${{ parameters.isStepOutputVariable }}]$accessToken"
--------------------------------------------------------------------------------
/eng/common/templates-official/steps/publish-logs.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | StageLabel: ''
3 | JobLabel: ''
4 |
5 | steps:
6 | - task: Powershell@2
7 | displayName: Prepare Binlogs to Upload
8 | inputs:
9 | targetType: inline
10 | script: |
11 | New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/
12 | Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/
13 | continueOnError: true
14 | condition: always()
15 |
16 | - task: 1ES.PublishBuildArtifacts@1
17 | displayName: Publish Logs
18 | inputs:
19 | PathtoPublish: '$(Build.SourcesDirectory)/PostBuildLogs'
20 | PublishLocation: Container
21 | ArtifactName: PostBuildLogs
22 | continueOnError: true
23 | condition: always()
24 |
--------------------------------------------------------------------------------
/eng/common/templates-official/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/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/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 |
9 | jobs:
10 | - template: /eng/common/templates/jobs/jobs.yml
11 | parameters:
12 | enableMicrobuild: false
13 | enablePublishBuildArtifacts: false
14 | enablePublishTestResults: false
15 | enablePublishBuildAssets: false
16 | enablePublishUsingPipelines: false
17 | enableTelemetry: true
18 |
19 | variables:
20 | - group: Publish-Build-Assets
21 | # The Guardian version specified in 'eng/common/sdl/packages.config'. This value must be kept in
22 | # sync with the packages.config file.
23 | - name: DefaultGuardianVersion
24 | value: 0.109.0
25 | - name: GuardianPackagesConfigFile
26 | value: $(Build.SourcesDirectory)\eng\common\sdl\packages.config
27 | - name: GuardianVersion
28 | value: ${{ coalesce(parameters.overrideGuardianVersion, '$(DefaultGuardianVersion)') }}
29 |
30 | jobs: ${{ parameters.jobs }}
31 |
32 |
--------------------------------------------------------------------------------
/eng/common/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: MaestroApiAccessToken
12 | value: $(MaestroAccessToken)
13 | - name: MaestroApiVersion
14 | value: "2020-02-20"
15 |
16 | - name: SourceLinkCLIVersion
17 | value: 3.0.0
18 | - name: SymbolToolVersion
19 | value: 1.0.1
20 |
21 | - name: runCodesignValidationInjection
22 | value: false
23 |
--------------------------------------------------------------------------------
/eng/common/templates/post-build/trigger-subscription.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | ChannelId: 0
3 |
4 | steps:
5 | - task: PowerShell@2
6 | displayName: Triggering subscriptions
7 | inputs:
8 | filePath: $(Build.SourcesDirectory)/eng/common/post-build/trigger-subscriptions.ps1
9 | arguments: -SourceRepo $(Build.Repository.Uri)
10 | -ChannelId ${{ parameters.ChannelId }}
11 | -MaestroApiAccessToken $(MaestroAccessToken)
12 | -MaestroApiEndPoint $(MaestroApiEndPoint)
13 | -MaestroApiVersion $(MaestroApiVersion)
14 |
--------------------------------------------------------------------------------
/eng/common/templates/steps/add-build-to-channel.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | ChannelId: 0
3 |
4 | steps:
5 | - task: PowerShell@2
6 | displayName: Add Build to Channel
7 | inputs:
8 | filePath: $(Build.SourcesDirectory)/eng/common/post-build/add-build-to-channel.ps1
9 | arguments: -BuildId $(BARBuildId)
10 | -ChannelId ${{ parameters.ChannelId }}
11 | -MaestroApiAccessToken $(MaestroApiAccessToken)
12 | -MaestroApiEndPoint $(MaestroApiEndPoint)
13 | -MaestroApiVersion $(MaestroApiVersion)
14 |
--------------------------------------------------------------------------------
/eng/common/templates/steps/build-reason.yml:
--------------------------------------------------------------------------------
1 | # build-reason.yml
2 | # Description: runs steps if build.reason condition is valid. conditions is a string of valid build reasons
3 | # to include steps (',' separated).
4 | parameters:
5 | conditions: ''
6 | steps: []
7 |
8 | steps:
9 | - ${{ if and( not(startsWith(parameters.conditions, 'not')), contains(parameters.conditions, variables['build.reason'])) }}:
10 | - ${{ parameters.steps }}
11 | - ${{ if and( startsWith(parameters.conditions, 'not'), not(contains(parameters.conditions, variables['build.reason']))) }}:
12 | - ${{ parameters.steps }}
13 |
--------------------------------------------------------------------------------
/eng/common/templates/steps/component-governance.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | disableComponentGovernance: false
3 | componentGovernanceIgnoreDirectories: ''
4 |
5 | steps:
6 | - ${{ if eq(parameters.disableComponentGovernance, 'true') }}:
7 | - script: echo "##vso[task.setvariable variable=skipComponentGovernanceDetection]true"
8 | displayName: Set skipComponentGovernanceDetection variable
9 | - ${{ if ne(parameters.disableComponentGovernance, 'true') }}:
10 | - task: ComponentGovernanceComponentDetection@0
11 | continueOnError: true
12 | inputs:
13 | ignoreDirectories: ${{ parameters.componentGovernanceIgnoreDirectories }}
--------------------------------------------------------------------------------
/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 | 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 |
18 | steps:
19 | - ${{ if ne(variables['System.TeamProject'], 'public') }}:
20 | - template: /eng/common/templates/steps/get-delegation-sas.yml
21 | parameters:
22 | federatedServiceConnection: ${{ parameters.federatedServiceConnection }}
23 | outputVariableName: ${{ parameters.outputVariableName }}
24 | expiryInHours: ${{ parameters.expiryInHours }}
25 | base64Encode: ${{ parameters.base64Encode }}
26 | storageAccount: dotnetbuilds
27 | container: internal
28 | permissions: rl
29 |
--------------------------------------------------------------------------------
/eng/common/templates/steps/get-federated-access-token.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | - name: federatedServiceConnection
3 | type: string
4 | - name: outputVariableName
5 | type: string
6 | - name: stepName
7 | type: string
8 | default: 'getFederatedAccessToken'
9 | - name: condition
10 | type: string
11 | default: ''
12 | # Resource to get a token for. Common values include:
13 | # - '499b84ac-1321-427f-aa17-267ca6975798' for Azure DevOps
14 | # - 'https://storage.azure.com/' for storage
15 | # Defaults to Azure DevOps
16 | - name: resource
17 | type: string
18 | default: '499b84ac-1321-427f-aa17-267ca6975798'
19 | - name: isStepOutputVariable
20 | type: boolean
21 | default: false
22 |
23 | steps:
24 | - task: AzureCLI@2
25 | displayName: 'Getting federated access token for feeds'
26 | name: ${{ parameters.stepName }}
27 | ${{ if ne(parameters.condition, '') }}:
28 | condition: ${{ parameters.condition }}
29 | inputs:
30 | azureSubscription: ${{ parameters.federatedServiceConnection }}
31 | scriptType: 'pscore'
32 | scriptLocation: 'inlineScript'
33 | inlineScript: |
34 | $accessToken = az account get-access-token --query accessToken --resource ${{ parameters.resource }} --output tsv
35 | if ($LASTEXITCODE -ne 0) {
36 | Write-Error "Failed to get access token for resource '${{ parameters.resource }}'"
37 | exit 1
38 | }
39 | Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value"
40 | Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true;isOutput=${{ parameters.isStepOutputVariable }}]$accessToken"
--------------------------------------------------------------------------------
/eng/common/templates/steps/publish-logs.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | StageLabel: ''
3 | JobLabel: ''
4 |
5 | steps:
6 | - task: Powershell@2
7 | displayName: Prepare Binlogs to Upload
8 | inputs:
9 | targetType: inline
10 | script: |
11 | New-Item -ItemType Directory $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/
12 | Move-Item -Path $(Build.SourcesDirectory)/artifacts/log/Debug/* $(Build.SourcesDirectory)/PostBuildLogs/${{parameters.StageLabel}}/${{parameters.JobLabel}}/
13 | continueOnError: true
14 | condition: always()
15 |
16 | - task: PublishBuildArtifacts@1
17 | displayName: Publish Logs
18 | inputs:
19 | PathtoPublish: '$(Build.SourcesDirectory)/PostBuildLogs'
20 | PublishLocation: Container
21 | ArtifactName: PostBuildLogs
22 | continueOnError: true
23 | condition: always()
24 |
--------------------------------------------------------------------------------
/eng/common/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/templates/steps/run-on-unix.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | agentOs: ''
3 | steps: []
4 |
5 | steps:
6 | - ${{ if ne(parameters.agentOs, 'Windows_NT') }}:
7 | - ${{ parameters.steps }}
8 |
--------------------------------------------------------------------------------
/eng/common/templates/steps/run-on-windows.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | agentOs: ''
3 | steps: []
4 |
5 | steps:
6 | - ${{ if eq(parameters.agentOs, 'Windows_NT') }}:
7 | - ${{ parameters.steps }}
8 |
--------------------------------------------------------------------------------
/eng/common/templates/steps/run-script-ifequalelse.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | # if parameter1 equals parameter 2, run 'ifScript' command, else run 'elsescript' command
3 | parameter1: ''
4 | parameter2: ''
5 | ifScript: ''
6 | elseScript: ''
7 |
8 | # name of script step
9 | name: Script
10 |
11 | # display name of script step
12 | displayName: If-Equal-Else Script
13 |
14 | # environment
15 | env: {}
16 |
17 | # conditional expression for step execution
18 | condition: ''
19 |
20 | steps:
21 | - ${{ if and(ne(parameters.ifScript, ''), eq(parameters.parameter1, parameters.parameter2)) }}:
22 | - script: ${{ parameters.ifScript }}
23 | name: ${{ parameters.name }}
24 | displayName: ${{ parameters.displayName }}
25 | env: ${{ parameters.env }}
26 | condition: ${{ parameters.condition }}
27 |
28 | - ${{ if and(ne(parameters.elseScript, ''), ne(parameters.parameter1, parameters.parameter2)) }}:
29 | - script: ${{ parameters.elseScript }}
30 | name: ${{ parameters.name }}
31 | displayName: ${{ parameters.displayName }}
32 | env: ${{ parameters.env }}
33 | condition: ${{ parameters.condition }}
--------------------------------------------------------------------------------
/eng/common/templates/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/dependencies.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | 13.0.3
4 | 10.0.0
5 | 5.1.5
6 | 1.10.4
7 | 3.0.0
8 | 8.0.0
9 |
10 |
11 |
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "8.0.115",
4 | "rollForward": "latestMajor",
5 | "allowPrerelease": true
6 | },
7 | "tools": {
8 | "dotnet": "8.0.115"
9 | },
10 | "msbuild-sdks": {
11 | "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.25230.1"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/samples/hello/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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Threading.Tasks;
9 | using Microsoft.AspNetCore.Hosting;
10 | using Microsoft.Extensions.Configuration;
11 | using Microsoft.Extensions.Hosting;
12 | using Microsoft.Extensions.Logging;
13 |
14 | namespace hello
15 | {
16 | public class Program
17 | {
18 | public static void Main(string[] args)
19 | {
20 | CreateHostBuilder(args).Build().Run();
21 | }
22 |
23 | public static IHostBuilder CreateHostBuilder(string[] args) =>
24 | Host.CreateDefaultBuilder(args)
25 | .ConfigureWebHostDefaults(webBuilder =>
26 | {
27 | webBuilder.UseStartup();
28 | });
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/samples/hello/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/samples/hello/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft": "Warning",
6 | "Microsoft.Hosting.Lifetime": "Information"
7 | }
8 | },
9 | "AllowedHosts": "*"
10 | }
11 |
--------------------------------------------------------------------------------
/samples/hello/hello.benchmarks.yml:
--------------------------------------------------------------------------------
1 | imports:
2 | - https://raw.githubusercontent.com/dotnet/crank/main/src/Microsoft.Crank.Jobs.Bombardier/bombardier.yml
3 |
4 | jobs:
5 | server:
6 | sources:
7 | crank:
8 | repository: https://github.com/dotnet/crank
9 | branchOrCommit: main
10 | project: crank/samples/hello/hello.csproj
11 | readyStateText: Application started.
12 |
13 | scenarios:
14 | hello:
15 | application:
16 | job: server
17 | load:
18 | job: bombardier
19 | variables:
20 | serverPort: 5000
21 | path: /
22 |
23 | profiles:
24 | local:
25 | variables:
26 | serverAddress: localhost
27 | jobs:
28 | application:
29 | endpoints:
30 | - http://localhost:5010
31 | load:
32 | endpoints:
33 | - http://localhost:5010
34 |
--------------------------------------------------------------------------------
/samples/hello/hello.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/samples/local/local.benchmarks.yml:
--------------------------------------------------------------------------------
1 | imports:
2 | - https://raw.githubusercontent.com/dotnet/crank/main/src/Microsoft.Crank.Jobs.Bombardier/bombardier.yml
3 |
4 | jobs:
5 | server:
6 | sources:
7 | hello-sample:
8 | localFolder: ../../samples/hello
9 | project: hello-sample/hello.csproj
10 | readyStateText: Application started.
11 |
12 | scenarios:
13 | hello:
14 | application:
15 | job: server
16 | load:
17 | job: bombardier
18 | variables:
19 | serverPort: 5000
20 | path: /
21 |
22 | profiles:
23 | local:
24 | variables:
25 | serverAddress: localhost
26 | jobs:
27 | application:
28 | endpoints:
29 | - http://localhost:5010
30 | load:
31 | endpoints:
32 | - http://localhost:5010
33 |
--------------------------------------------------------------------------------
/samples/micro/Md5VsSha256.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Security.Cryptography;
7 | using BenchmarkDotNet.Attributes;
8 |
9 | namespace Micro
10 | {
11 | public class Md5VsSha256
12 | {
13 | [Params(100, 500)]
14 | public int N { get; set;}
15 | private readonly byte[] data;
16 |
17 | private readonly SHA256 sha256 = SHA256.Create();
18 | private readonly MD5 md5 = MD5.Create();
19 |
20 | public Md5VsSha256()
21 | {
22 | data = new byte[N];
23 | new Random(42).NextBytes(data);
24 | }
25 |
26 | [Benchmark]
27 | public byte[] Sha256() => sha256.ComputeHash(data);
28 |
29 | [Benchmark]
30 | public byte[] Md5() => md5.ComputeHash(data);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/samples/micro/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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Threading.Tasks;
9 | using BenchmarkDotNet.Running;
10 |
11 | namespace Micro
12 | {
13 | public class Program
14 | {
15 | public static void Main(string[] args)
16 | {
17 | BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/samples/micro/dotnet.benchmarks.yml:
--------------------------------------------------------------------------------
1 | jobs:
2 | dotnet:
3 | sources:
4 | performance:
5 | repository: https://github.com/dotnet/performance
6 | branchOrCommit: main
7 | project: performance/src/benchmarks/micro/MicroBenchmarks.csproj
8 | variables:
9 | filterArg: "*"
10 | jobArg: short
11 | arguments: --job {{jobArg}} --filter {{filterArg}} --memory
12 | framework: netcoreapp3.1
13 | options:
14 | benchmarkDotNet: true
15 |
16 | scenarios:
17 |
18 | Linq:
19 | application:
20 | job: dotnet
21 | variables:
22 | filterArg: "*LinqBenchmarks*"
23 |
24 | Sockets:
25 | application:
26 | job: dotnet
27 | variables:
28 | filterArg: "*SocketSendReceivePerfTest*"
29 |
30 | profiles:
31 | local:
32 | jobs:
33 | application:
34 | endpoints:
35 | - http://localhost:5010
36 |
--------------------------------------------------------------------------------
/samples/micro/micro.benchmarks.yml:
--------------------------------------------------------------------------------
1 | jobs:
2 | benchmarks:
3 | sources:
4 | micro:
5 | localFolder: .
6 | project: micro/micro.csproj
7 | variables:
8 | filterArg: "*"
9 | jobArg: short
10 | arguments: --job {{jobArg}} --filter {{filterArg}} --memory
11 | options:
12 | benchmarkDotNet: true
13 |
14 | scenarios:
15 | Md5VsSha256:
16 | application:
17 | job: benchmarks
18 |
19 | profiles:
20 | local:
21 | jobs:
22 | application:
23 | endpoints:
24 | - http://localhost:5010
25 |
--------------------------------------------------------------------------------
/samples/micro/micro.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.1
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/samples/netty/netty.benchmarks.yml:
--------------------------------------------------------------------------------
1 | imports:
2 | - https://raw.githubusercontent.com/dotnet/crank/main/src/Microsoft.Crank.Jobs.Wrk/wrk.yml
3 |
4 | variables:
5 | localEndpoint: http://localhost:5010
6 |
7 | jobs:
8 | server:
9 | sources:
10 | techempower:
11 | repository: https://github.com/TechEmpower/FrameworkBenchmarks
12 | branchOrCommit: master
13 | dockerFile: techempower/frameworks/Java/netty/netty.dockerfile
14 | dockerImageName: netty
15 | dockerContextDirectory: techempower/frameworks/Java/netty
16 | port: 8080
17 |
18 | scenarios:
19 | netty:
20 | application:
21 | job: server
22 | load:
23 | job: wrk
24 | variables:
25 | serverPort: 8080
26 | path: /plaintext
27 |
28 | profiles:
29 | local:
30 | variables:
31 | serverAddress: localhost
32 | jobs:
33 | application:
34 | endpoints:
35 | - "{{ localEndpoint }}"
36 | load:
37 | endpoints:
38 | - "{{ localEndpoint }}"
39 |
--------------------------------------------------------------------------------
/samples/post/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Net.Http.Json;
2 |
3 | Console.WriteLine("Application started.");
4 |
5 | var agentUrl = args[0];
6 |
7 | Console.WriteLine($"BaseAddress: {agentUrl}");
8 |
9 | using var httpClient = new HttpClient();
10 |
11 | var response = await httpClient.PostAsync($"{agentUrl}/metadata?name=cpu&aggregate=max&reduce=max&format=n0&longDescription=Long%20description&shortDescription=Short%20description", new StringContent(""));
12 |
13 | Console.WriteLine(response);
14 |
15 | response = await httpClient.PostAsync($"{agentUrl}/measurement?name=cpu×tamp=2024-02-23T14:00:00Z&value=123.456", new StringContent(""));
16 |
17 | Console.WriteLine(response);
18 |
19 | var statistics = new
20 | {
21 | Metadata = new[]
22 | {
23 | new
24 | {
25 | Name = "metadata1",
26 | Aggregate = "Max",
27 | Reduce = "Max",
28 | Format = "n0",
29 | LongDescription = "Long description 1",
30 | ShortDescription = "Short description 1"
31 | },
32 | new
33 | {
34 | Name = "metadata2",
35 | Aggregate = "Min",
36 | Reduce = "Min",
37 | Format = "n2",
38 | LongDescription = "Long description 2",
39 | ShortDescription = "Short description 2"
40 | }
41 | },
42 |
43 | Measurements = new[]
44 | {
45 | new
46 | {
47 | Name = "metadata1",
48 | Timestamp = "2024-02-23T14:00:00Z",
49 | Value = 123.456M
50 | },
51 | new
52 | {
53 | Name = "metadata2",
54 | Timestamp = "2024-02-23T14:00:00Z",
55 | Value = 123.456M
56 | }
57 | }
58 | };
59 |
60 |
61 | response = await httpClient.PostAsJsonAsync($"{agentUrl}/statistics", statistics);
62 |
63 | Console.WriteLine(response);
64 |
--------------------------------------------------------------------------------
/samples/post/post.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/samples/precommand/precommand.benchmarks.yml:
--------------------------------------------------------------------------------
1 | imports:
2 | - https://raw.githubusercontent.com/dotnet/crank/main/src/Microsoft.Crank.Jobs.Bombardier/bombardier.yml
3 |
4 | commands:
5 | # Assumes that the crank repository is the working directory
6 | buildHello:
7 | - condition: job.environment.platform == "windows"
8 | scriptType: batch
9 | script: dotnet build -c Release -f net8.0 .\samples\hello\hello.csproj
10 | - condition: job.environment.platform != "windows"
11 | scriptType: bash
12 | script: dotnet build -c Release -f net8.0 ./samples/hello/hello.csproj
13 |
14 | jobs:
15 | server:
16 | sources:
17 | hello:
18 | localFolder: ../../artifacts/bin/hello/Release/net8.0
19 | executable: dotnet
20 | arguments: hello/hello.dll
21 | noBuild: true
22 | beforeJob:
23 | - buildHello
24 | readyStateText: Application started.
25 |
26 | scenarios:
27 | hello:
28 | application:
29 | job: server
30 | load:
31 | job: bombardier
32 | variables:
33 | serverPort: 5000
34 | path: /
35 |
36 | profiles:
37 | local:
38 | variables:
39 | serverAddress: localhost
40 | jobs:
41 | application:
42 | endpoints:
43 | - http://localhost:5010
44 | load:
45 | endpoints:
46 | - http://localhost:5010
47 |
--------------------------------------------------------------------------------
/samples/scripts/scripts.benchmarks.yml:
--------------------------------------------------------------------------------
1 | defaultScripts:
2 | - |
3 | console.log("this section is loaded by default and before named scripts")
4 |
5 | function percentile(items, th) {
6 | var ordered = items.sort((a, b) => a - b); // by default sort() uses ordinal comparison
7 | index = Math.max(0, Math.round(ordered.length * th / 100) - 1);
8 | return ordered[index];
9 | }
10 |
11 | scripts:
12 |
13 | # displays a message using all different colors
14 | say_hello: |
15 | console.log("hello")
16 | console.info("world")
17 | console.warn("this is")
18 | console.error("scary")
19 |
20 | # records the current date and time as a custom property
21 | add_current_time: |
22 | benchmarks.properties["time"] = new Date().toISOString();
23 |
24 | # calculats the allocations per request by using results from application and load
25 | add_allocations_per_request: |
26 | var allocations = benchmarks.jobs.application.results["runtime-counter/alloc-rate"]
27 | var rps = benchmarks.jobs.load.results["wrk/requests"];
28 | benchmarks.jobs.application.results["alloc-per-request"] = allocations / rps;
29 |
30 | # computes the 95th percentile of the working set from all the data points (measurements)
31 | add_p95_memory: |
32 | var memories = benchmarks.jobs.application.measurements[0]
33 | .filter(m => m.name == "benchmarks/working-set")
34 | .map(x => x.value);
35 | var value = percentile(memories, 95);
36 | console.info(`p95 of working set is ${value}`);
37 | benchmarks.jobs.application.results["benchmarks/working-set/p95"] = value;
38 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Agent/CompositeRelayServer.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using Microsoft.AspNetCore.Hosting.Server;
11 | using Microsoft.AspNetCore.Http.Features;
12 |
13 | namespace Microsoft.Crank.Agent
14 | {
15 | public class CompositeServer : IServer
16 | {
17 | private readonly IEnumerable _servers;
18 |
19 | public CompositeServer(IEnumerable servers)
20 | {
21 | if (servers == null)
22 | {
23 | throw new ArgumentNullException(nameof(servers));
24 | }
25 |
26 | if (servers.Count() < 2)
27 | {
28 | throw new ArgumentException("Expected at least 2 servers.", nameof(servers));
29 | }
30 |
31 | _servers = servers;
32 | }
33 | public IFeatureCollection Features => _servers.First().Features;
34 |
35 | public void Dispose()
36 | {
37 | foreach (var server in _servers)
38 | {
39 | server.Dispose();
40 | }
41 | }
42 |
43 | public async Task StartAsync(IHttpApplication application, CancellationToken cancellationToken) where TContext : notnull
44 | {
45 | foreach (var server in _servers)
46 | {
47 | await server.StartAsync(application, cancellationToken);
48 | }
49 | }
50 |
51 | public async Task StopAsync(CancellationToken cancellationToken)
52 | {
53 | foreach (var server in _servers)
54 | {
55 | await server.StopAsync(cancellationToken);
56 | }
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Agent/Controllers/HomeController.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Reflection;
7 | using Microsoft.AspNetCore.Mvc;
8 |
9 | namespace Microsoft.Crank.Agent.Controllers
10 | {
11 | [Route("")]
12 | public class HomeController : Controller
13 | {
14 | [HttpGet]
15 | public IActionResult Index()
16 | {
17 | return RedirectToAction("GetQueue", "Jobs");
18 | }
19 |
20 | [HttpGet("info")]
21 | public IActionResult Info()
22 | {
23 | return Json(new
24 | {
25 | hw = Startup.Hardware.ToString(),
26 | env = Startup.HardwareVersion.ToString(),
27 | os = Startup.OperatingSystem.ToString(),
28 | arch = System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture.ToString(),
29 | proc = Environment.ProcessorCount,
30 | version = typeof(HomeController).GetTypeInfo().Assembly.GetCustomAttribute()?.InformationalVersion
31 | });
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Agent/GZipFileResult.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Globalization;
6 | using System.IO;
7 | using System.IO.Compression;
8 | using System.Threading.Tasks;
9 | using Microsoft.AspNetCore.Http;
10 | using Microsoft.AspNetCore.Mvc;
11 | using Microsoft.Net.Http.Headers;
12 |
13 | public class GZipFileResult : ActionResult
14 | {
15 | public GZipFileResult(string filename)
16 | {
17 | FileName = filename;
18 | }
19 |
20 | public string FileName { get; set; }
21 |
22 | public override async Task ExecuteResultAsync(ActionContext context)
23 | {
24 | context.HttpContext.Response.Headers.Append(HeaderNames.Vary, HeaderNames.ContentEncoding);
25 | await using var stream = File.OpenRead(FileName);
26 |
27 | context.HttpContext.Response.Headers["FileLength"] = new FileInfo(FileName).Length.ToString(CultureInfo.InvariantCulture);
28 |
29 | if (context.HttpContext.Request.Headers.TryGetValue(HeaderNames.AcceptEncoding, out var acceptEncoding)
30 | && acceptEncoding.ToString().Contains("gzip"))
31 | {
32 | await using var gzipStream = new GZipStream(context.HttpContext.Response.Body, CompressionLevel.Fastest);
33 |
34 | context.HttpContext.Response.Headers[HeaderNames.ContentEncoding] = "gzip";
35 | await stream.CopyToAsync(gzipStream);
36 | await stream.FlushAsync();
37 | await gzipStream.FlushAsync();
38 | }
39 | else
40 | {
41 | await stream.CopyToAsync(context.HttpContext.Response.Body);
42 | await stream.FlushAsync();
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Agent/JobContext.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Diagnostics;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using Microsoft.Crank.Models;
11 | using Microsoft.Diagnostics.NETCore.Client;
12 |
13 | namespace Microsoft.Crank.Agent
14 | {
15 | ///
16 | /// Contains the state of a Job when it's run by the Agent.
17 | ///
18 | public class JobContext
19 | {
20 | public Job Job { get; set; }
21 | public Process Process { get; set; }
22 | public string WorkingDirectory { get; set; }
23 | public Timer Timer { get; set; }
24 | public bool Disposed { get; set; }
25 | public string BenchmarksDir { get; set; }
26 | public DateTime StartMonitorTime { get; set; } = DateTime.UtcNow;
27 | public DateTime NextMeasurement { get; set; } = DateTime.UtcNow;
28 |
29 | public string TempDir { get; set; }
30 | public bool TempDirUsesSourceKey { get; set; }
31 | public Dictionary SourceDirs { get; set; } = new();
32 | public string DockerImage { get; set; }
33 | public string DockerContainerId { get; set; }
34 |
35 | public ulong EventPipeSessionId { get; set; }
36 | public Task EventPipeTask { get; set; }
37 | public bool EventPipeTerminated { get; set; }
38 |
39 | public EventPipeSession EventPipeSession { get; set; }
40 | public Task CountersTask { get; set; }
41 | public TaskCompletionSource CountersCompletionSource { get; set; }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Agent/JobResult.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using Microsoft.AspNetCore.Mvc;
7 | using Microsoft.Crank.Models;
8 |
9 | namespace Microsoft.Crank.Agent
10 | {
11 | public class JobResult
12 | {
13 | public JobResult(Job job, IUrlHelper urlHelper)
14 | {
15 | Id = job.Id;
16 | RunId = job.RunId;
17 | State = job.State.ToString();
18 | DetailsUrl = urlHelper.ActionLink("GetById", "Jobs", new { Id });
19 | BuildLogsUrl = urlHelper.ActionLink("BuildLog", "Jobs", new { Id });
20 | OutputLogsUrl = urlHelper.ActionLink("Output", "Jobs", new { Id });
21 | }
22 |
23 | public int Id { get; set; }
24 | public string RunId { get; set; }
25 | public string State { get; set;}
26 | public string DetailsUrl { get; set; }
27 | public string BuildLogsUrl { get; set; }
28 | public string OutputLogsUrl { get; set; }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Agent/MachineCounters/MachineCountersEventSource.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.Tracing;
2 |
3 | namespace Microsoft.Crank.Agent.MachineCounters
4 | {
5 | [EventSource(Name = "MachineCountersEventSource")]
6 | internal class MachineCountersEventSource : EventSource
7 | {
8 | ///
9 | /// Should not be disposed -> is a singleton for the application lifetime
10 | ///
11 | public static readonly MachineCountersEventSource Log = new MachineCountersEventSource();
12 |
13 | public void WriteCounterValue(string counterName, double value)
14 | => WriteEvent(1, counterName, value);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Agent/MachineCounters/OS/IMachinePerformanceCounterEmitter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace Microsoft.Crank.Agent.MachineCounters.OS
4 | {
5 | internal interface IMachinePerformanceCounterEmitter : IDisposable
6 | {
7 | string MeasurementName { get; }
8 | string CounterName { get; }
9 |
10 | bool TryStart();
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Agent/Measurements.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Crank.Agent
2 | {
3 | public class Measurements
4 | {
5 | public const string BenchmarksCpu = "benchmarks/cpu";
6 | public const string BenchmarksCpuRaw = "benchmarks/cpu/raw";
7 | public const string BenchmarksWorkingSet = "benchmarks/working-set";
8 | public const string BenchmarksPrivateMemory = "benchmarks/private-memory";
9 | public const string BenchmarksBuildTime = "benchmarks/build-time";
10 | public const string BenchmarksStartTime = "benchmarks/start-time";
11 | public const string BenchmarksPublishedSize = "benchmarks/published-size";
12 | public const string BenchmarksPublishedNativeAOTSizeRaw = "benchmarks/published-nativeaot-size/raw";
13 | public const string BenchmarksSymbolsSize = "benchmarks/symbols-size";
14 | public const string BenchmarksMemorySwap = "benchmarks/memory/swap";
15 | public const string BenchmarksCpuPeriodsTotal = "benchmarks/cpu/periods/total";
16 | public const string BenchmarksCpuPeriodsThrottled = "benchmarks/cpu/periods/throttled";
17 | public const string BenchmarksCpuThrottled = "benchmarks/cpu/throttled";
18 | public const string BenchmarksNetSdkVersion = "netSdkVersion";
19 | public const string BenchmarksAspNetCoreVersion = "AspNetCoreVersion";
20 | public const string BenchmarksNetCoreAppVersion = "NetCoreAppVersion";
21 |
22 | public const string BenchmarksCpuGlobal = "benchmarks/cpu/global";
23 | public const string BenchmarksProcessCpuFormat = "benchmarks/{0}/cpu";
24 | public static string GetBenchmarkProcessCpu(string processName) => string.Format(BenchmarksProcessCpuFormat, processName);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Agent/NativeMethods.txt:
--------------------------------------------------------------------------------
1 | AdjustTokenPrivileges
2 | AssignProcessToJobObject
3 | CloseHandle
4 | CreateIoCompletionPort
5 | CreateJobObject
6 | CreateProcess
7 | DebugActiveProcessStop
8 | DebugSetProcessKillOnExit
9 | DuplicateHandle
10 | DuplicateTokenEx
11 | GetConsoleWindow
12 | GetCurrentProcess
13 | GetExitCodeProcess
14 | GetProcessAffinityMask
15 | GetProcessGroupAffinity
16 | GetNumaHighestNodeNumber
17 | GetNumaNodeProcessorMaskEx
18 | GetSystemCpuSetInformation
19 | IsProcessInJob
20 | LookupPrivilegeValue
21 | NtQueryInformationProcess
22 | OpenJobObject
23 | OpenProcess
24 | OpenProcessToken
25 | ResumeThread
26 | ReadProcessMemory
27 | QueryInformationJobObject
28 | SetInformationJobObject
29 | ShowWindow
30 | TerminateJobObject
31 | TerminateProcess
32 | VirtualAllocEx
33 | VirtualFreeEx
34 | WaitForSingleObject
35 | WriteProcessMemory
36 |
37 | GROUP_AFFINITY
38 | IO_COUNTERS
39 | JOBOBJECT_BASIC_ACCOUNTING_INFORMATION
40 | JOBOBJECT_CPU_RATE_CONTROL_INFORMATION
41 | JOBOBJECT_EXTENDED_LIMIT_INFORMATION
42 | JOBOBJECT_NET_RATE_CONTROL_INFORMATION
43 | TOKEN_PRIVILEGES
44 |
45 | FILE_ACCESS_RIGHTS
46 | INFINITE
47 | INVALID_HANDLE_VALUE
48 | JOB_OBJECT_ASSIGN_PROCESS
49 | JOB_OBJECT_LIMIT
50 | JOB_OBJECT_MSG_END_OF_JOB_TIME
51 | JOB_OBJECT_MSG_ABNORMAL_EXIT_PROCESS
52 | JOB_OBJECT_MSG_ACTIVE_PROCESS_LIMIT
53 | JOB_OBJECT_MSG_ACTIVE_PROCESS_ZERO
54 | JOB_OBJECT_MSG_END_OF_PROCESS_TIME
55 | JOB_OBJECT_MSG_EXIT_PROCESS
56 | JOB_OBJECT_MSG_JOB_MEMORY_LIMIT
57 | JOB_OBJECT_MSG_NEW_PROCESS
58 | JOB_OBJECT_MSG_PROCESS_MEMORY_LIMIT
59 | JOB_OBJECT_NET_RATE_CONTROL_MAX_DSCP_TAG
60 | JOB_OBJECT_SET_ATTRIBUTES
61 | JOB_OBJECT_SET_SECURITY_ATTRIBUTES
62 | JOB_OBJECT_QUERY
63 | JOB_OBJECT_TERMINATE
64 | PROCESS_CREATION_FLAGS
65 | PROCESSINFOCLASS
66 | WIN32_ERROR
67 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Agent/PackageTypes.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.Agent
6 | {
7 | internal enum PackageTypes
8 | {
9 | Sdk,
10 | NetCoreApp,
11 | AspNetCore,
12 | WindowsDesktop
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Agent/ProcessResult.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.Agent
6 | {
7 | public class ProcessResult
8 | {
9 | public ProcessResult(int exitCode, string standardOutput, string standardError)
10 | {
11 | ExitCode = exitCode;
12 | StandardOutput = standardOutput;
13 | StandardError = standardError;
14 | }
15 |
16 | public string StandardOutput { get; }
17 | public string StandardError { get; }
18 | public int ExitCode { get; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Agent/Repository/IIdentifiable.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Repository
6 | {
7 | public interface IIdentifiable
8 | {
9 | int Id { get; set; }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Agent/Repository/IJobRepository.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Collections.Generic;
6 | using Microsoft.Crank.Models;
7 |
8 | namespace Repository
9 | {
10 | public interface IJobRepository
11 | {
12 | Job Add(Job item);
13 | IEnumerable GetAll();
14 | Job Find(int id);
15 | Job Remove(int id);
16 | void Update(Job item);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Agent/Repository/InMemoryJobRepository.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Concurrent;
7 | using System.Collections.Generic;
8 | using Microsoft.Crank.Models;
9 |
10 | namespace Repository
11 | {
12 | public class InMemoryJobRepository : IJobRepository
13 | {
14 | private readonly object _lock = new object();
15 | private readonly ConcurrentDictionary _items = new ConcurrentDictionary();
16 | private int _nextId = 1;
17 |
18 | public Job Add(Job item)
19 | {
20 | if (item.Id != 0)
21 | {
22 | throw new ArgumentException("item.Id must be 0.");
23 | }
24 |
25 | lock (_lock)
26 | {
27 | var id = _nextId;
28 | _nextId++;
29 | item.Id = id;
30 | _items[id] = item;
31 | return item;
32 | }
33 | }
34 |
35 | public Job Find(int id)
36 | {
37 | _items.TryGetValue(id, out var job);
38 |
39 | return job;
40 | }
41 |
42 | public IEnumerable GetAll()
43 | {
44 | return _items.Values;
45 | }
46 |
47 | public Job Remove(int id)
48 | {
49 | _items.TryRemove(id, out var job);
50 |
51 | return job;
52 | }
53 |
54 | public void Update(Job item)
55 | {
56 | var oldItem = Find(item.Id);
57 |
58 | if (!object.ReferenceEquals(item, oldItem))
59 | {
60 | _items[item.Id] = item;
61 | }
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.AzureDevOpsWorker/DotNetToolSettings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.AzureDevOpsWorker/Microsoft.Crank.AzureDevOpsWorker.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | Execute crank jobs added to an Azure Service Bus queue by Azure DevOps.
6 | crank-azdo
7 | crank-azdo
8 | true
9 | true
10 | Exe
11 | Microsoft
12 | Microsoft.Crank.AzureDevOpsWorker
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | true
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | PreserveNewest
35 |
36 |
37 | PreserveNewest
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.AzureDevOpsWorker/ProcessResult.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.AzureDevOpsWorker
6 | {
7 | public class ProcessResult
8 | {
9 | public ProcessResult(int exitCode, string output, string error)
10 | {
11 | ExitCode = exitCode;
12 | Output = output;
13 | Error = error;
14 | }
15 |
16 | public string Error { get; }
17 | public int ExitCode { get; }
18 | public string Output { get; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.AzureDevOpsWorker/Records.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Crank.AzureDevOpsWorker
2 | {
3 | public class Records
4 | {
5 | public int Count { get; set; }
6 | public Record[] Value { get; set; }
7 | }
8 |
9 | public class Record
10 | {
11 | public string Id { get; set; }
12 | public string State { get; set; } // "completed", "pending"
13 | public string Result { get; set; } // "succeeded", "skipped", "failed", null
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.AzureDevOpsWorker/RetryHandler.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Net.Http;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 |
10 | namespace Microsoft.Crank.AzureDevOpsWorker
11 | {
12 | internal class RetryHandler : DelegatingHandler
13 | {
14 | private const int MaxRetries = 3;
15 |
16 | public RetryHandler(HttpMessageHandler innerHandler)
17 | : base(innerHandler)
18 | { }
19 |
20 | protected override async Task SendAsync(
21 | HttpRequestMessage request,
22 | CancellationToken cancellationToken)
23 | {
24 | HttpResponseMessage response = null;
25 | for (var i = 0; i < MaxRetries; i++)
26 | {
27 | response = await base.SendAsync(request, cancellationToken);
28 | if (response.IsSuccessStatusCode)
29 | {
30 | return response;
31 | }
32 |
33 | Console.WriteLine($"Request failed ({response.StatusCode}), retrying...");
34 |
35 | response.Dispose();
36 |
37 | // Wait 1 second before retrying
38 | await Task.Delay(1000, cancellationToken);
39 | }
40 |
41 | return response;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.AzureDevOpsWorker/TimeSpanConverter.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Text.Json;
7 | using System.Text.Json.Serialization;
8 |
9 | namespace Microsoft.Crank.AzureDevOpsWorker
10 | {
11 | public class TimeSpanConverter : JsonConverter
12 | {
13 | public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
14 | {
15 | return TimeSpan.Parse(reader.GetString());
16 | }
17 |
18 | public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
19 | {
20 | writer.WriteStringValue(value.ToString());
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Controller/ControllerException.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 |
7 | namespace Microsoft.Crank.Controller
8 | {
9 | public class ControllerException : Exception
10 | {
11 | public ControllerException(string message) : base(message)
12 | {
13 |
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Controller/CounterProfile.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Linq;
8 |
9 | namespace Microsoft.Crank.Controller
10 | {
11 | public class CounterProfile
12 | {
13 | public string Name { get; set; }
14 | public string DisplayName { get; set; }
15 | public string Description { get; set; }
16 | public string Format { get; set; }
17 | public Func, double> Compute { get; set; }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Controller/DotNetToolSettings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Controller/ExcludeOptions.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.Controller
6 | {
7 | public struct ExcludeOptions
8 | {
9 | public static readonly ExcludeOptions Empty = new ExcludeOptions();
10 |
11 | public int Low;
12 | public int High;
13 | public string Job;
14 | public string Result;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Controller/ExecutionResult.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using Microsoft.Crank.Models;
7 |
8 | namespace Microsoft.Crank.Controller
9 | {
10 | public class ExecutionResult
11 | {
12 | public int ReturnCode { get; set; }
13 |
14 | public JobResults JobResults { get; set; } = new JobResults();
15 |
16 | public Benchmark[] Benchmarks { get; set; } = Array.Empty();
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Controller/Headers.cs:
--------------------------------------------------------------------------------
1 | namespace Microsoft.Crank.Controller
2 | {
3 | public enum Headers
4 | {
5 | None,
6 | Html,
7 | Plaintext,
8 | Json
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Controller/JobDeadlockException.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 |
7 | namespace Microsoft.Crank.Controller
8 | {
9 | public class JobDeadlockException : Exception
10 | {
11 | public JobDeadlockException() : base()
12 | {
13 |
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Controller/JobDefinition.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using Newtonsoft.Json.Linq;
8 |
9 | namespace Microsoft.Crank.Controller
10 | {
11 | class JobDefinition : Dictionary
12 | {
13 | public JobDefinition() : base(StringComparer.OrdinalIgnoreCase)
14 | {
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Controller/JobView.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.Controller
6 | {
7 | public class JobView
8 | {
9 | public int Id { get; set; }
10 | public string RunId { get; set; }
11 | public string State { get; set;}
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Controller/JsonTypeResolver.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Globalization;
7 | using YamlDotNet.Core.Events;
8 | using YamlDotNet.Serialization;
9 |
10 | namespace Microsoft.Crank.Controller
11 | {
12 | /// Provides types resolution for YAML
13 | /// Without this booleans and numbers are parsed as strings
14 | public class JsonTypeResolver : INodeTypeResolver
15 | {
16 | public bool Resolve(NodeEvent nodeEvent, ref Type currentType)
17 | {
18 | if (nodeEvent is Scalar scalar && scalar.IsPlainImplicit)
19 | {
20 | if (decimal.TryParse(scalar.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var value))
21 | {
22 | currentType = typeof(decimal);
23 | return true;
24 | }
25 | else if (bool.TryParse(scalar.Value, out var b))
26 | {
27 | currentType = typeof(bool);
28 | return true;
29 | }
30 | }
31 |
32 | return false;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Controller/Microsoft.Crank.Controller.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | Schedules jobs on the benchmarks agent.
6 | crank
7 | crank
8 | true
9 | true
10 | Exe
11 | Microsoft
12 | Microsoft.Crank.Controller
13 | 12.0
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Controller/ProcessResult.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.PullRequestBot
6 | {
7 | public class ProcessResult
8 | {
9 | public ProcessResult(int exitCode, string standardOutput, string standardError)
10 | {
11 | ExitCode = exitCode;
12 | StandardOutput = standardOutput;
13 | StandardError = standardError;
14 | }
15 |
16 | public string StandardOutput { get; }
17 | public string StandardError { get; }
18 | public int ExitCode { get; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Controller/ScriptConsole.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Linq;
7 |
8 | namespace Microsoft.Crank.Controller
9 | {
10 | public class ScriptConsole
11 | {
12 | public bool HasErrors { get; private set; }
13 |
14 | public void Log(params object[] args)
15 | {
16 | if (args == null || args.Length == 0)
17 | {
18 | return;
19 | }
20 |
21 | Console.WriteLine(String.Join(" ", args));
22 | }
23 |
24 | public void Info(params object[] args)
25 | {
26 | if (args == null || args.Length == 0)
27 | {
28 | return;
29 | }
30 |
31 | Console.ForegroundColor = ConsoleColor.Green;
32 | Console.WriteLine(String.Join(" ", args));
33 | Console.ResetColor();
34 | }
35 |
36 | public void Warn(params object[] args)
37 | {
38 | if (args == null || args.Length == 0)
39 | {
40 | return;
41 | }
42 |
43 | Console.ForegroundColor = ConsoleColor.DarkYellow;
44 | Console.WriteLine(String.Join(" ", args));
45 | Console.ResetColor();
46 | }
47 |
48 | public void Error(params object[] args)
49 | {
50 | if (args == null || args.Length == 0)
51 | {
52 | return;
53 | }
54 |
55 | Console.ForegroundColor = ConsoleColor.Red;
56 | Console.WriteLine(String.Join(" ", args));
57 | Console.ResetColor();
58 |
59 | HasErrors = true;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Controller/ScriptFile.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.IO;
7 |
8 | namespace Microsoft.Crank.Controller
9 | {
10 | public class ScriptFile
11 | {
12 | public string ReadFile(string filename)
13 | {
14 | if (string.IsNullOrEmpty(filename))
15 | {
16 | return null;
17 | }
18 |
19 | return File.ReadAllText(filename);
20 | }
21 |
22 | public void WriteFile(string filename, string data)
23 | {
24 | if (String.IsNullOrEmpty(filename))
25 | {
26 | return;
27 | }
28 |
29 | File.WriteAllText(filename, data);
30 | }
31 |
32 | public bool Exists(string filename)
33 | {
34 | return !String.IsNullOrEmpty(filename) && File.Exists(filename);
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Controller/VariableParser.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Globalization;
7 | using McMaster.Extensions.CommandLineUtils.Abstractions;
8 | using Newtonsoft.Json.Linq;
9 |
10 | namespace Microsoft.Crank.Controller
11 | {
12 | public class VariableParser : IValueParser
13 | {
14 | public Type TargetType { get; } = typeof(ValueTuple);
15 |
16 | public object Parse(string argName, string value, CultureInfo culture)
17 | {
18 | if (string.IsNullOrWhiteSpace(value))
19 | {
20 | return default(ValueTuple);
21 | }
22 |
23 | var fragments = value!.Split('=', 2);
24 |
25 | var variableKey = fragments[0].Trim();
26 |
27 | try
28 | {
29 | // variable value, a json format value, such as json object, array, number, etc.
30 | var variableValue = JToken.Parse(fragments[1].Trim());
31 |
32 | return (variableKey, variableValue);
33 | }
34 | catch (Exception ex)
35 | {
36 | throw new FormatException(
37 | $"Invalid {argName} argument: '{variableKey}' is not a valid JSON value.",
38 | ex);
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.EventSources/Microsoft.Crank.EventSources.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | true
6 | Helper classes to register metrics with the Microsoft.Crank tools.
7 | true
8 | Microsoft
9 | Microsoft.Crank.EventSources
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.EventSources/Operations.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.EventSources
6 | {
7 | public enum Operations
8 | {
9 | First,
10 | Last,
11 | Avg,
12 | Sum,
13 | Median,
14 | Max,
15 | Min,
16 | Count,
17 | All,
18 | Delta // Difference between min and max of the set
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.JobOjectWrapper/Microsoft.Crank.JobObjectWrapper.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.JobOjectWrapper/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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Diagnostics;
6 |
7 | if (args.Length == 0)
8 | {
9 | Console.WriteLine("Arguments are missing.");
10 | Environment.Exit(-1);
11 | }
12 |
13 | var time = 1000;
14 | Console.WriteLine("Job Object Wrapper");
15 | Console.WriteLine($"Waiting for Job Object to be setup... {time}");
16 |
17 | await Task.Delay(time);
18 |
19 | var process = new Process()
20 | {
21 | StartInfo = {
22 | FileName = args[0],
23 | Arguments = string.Join(" ", args[1..]),
24 | UseShellExecute = false
25 | }
26 | };
27 |
28 | Console.WriteLine("Starting process...");
29 | Console.WriteLine($"Filename: {process.StartInfo.FileName}");
30 | Console.WriteLine($"Args: {process.StartInfo.Arguments}");
31 |
32 | process.Start();
33 | Console.Error.WriteLine($"##ChildProcessId:{process.Id}");
34 | process.WaitForExit();
35 |
36 | await Task.Delay(1000);
37 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.Bombardier/Microsoft.Crank.Jobs.Bombardier.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.H2Load/Microsoft.Crank.Jobs.H2Load.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.H2Load/h2load.yml:
--------------------------------------------------------------------------------
1 | variables:
2 | headers:
3 | none: ''
4 | grpc: '--header "content-type: application/grpc" --header "TE: trailers"'
5 | grpcDeadline: '--header "content-type: application/grpc" --header "TE: trailers" --header "grpc-timeout: 100S"'
6 | presetHeaders: none
7 |
8 | jobs:
9 | h2LoadClient:
10 | source:
11 | repository: https://github.com/dotnet/crank.git
12 | branchOrCommit: main
13 | project: src/Microsoft.Crank.Jobs.H2Load/Microsoft.Crank.Jobs.H2Load.csproj
14 | sourceKey: h2load
15 | noBuild: true
16 | readyStateText: H2Load Client
17 | waitForExit: true
18 | variables:
19 | threads: 1
20 | streams: 1
21 | connections: 1
22 | requests: 0
23 | duration: 15
24 | warmup: 5
25 | protocol: h2c
26 | body: ''
27 | bodyFile: '' # url for a file to use as the body content
28 | presetHeaders: none
29 | serverScheme: http
30 | serverAddress: localhost
31 | serverPort: 5000
32 | arguments: "-c {{connections}} -t {{threads}} -m {{streams}} -d {{duration}} -w {{warmup}} -n {{requests}} -u {% if serverUri == blank %} {{serverScheme}}://{{serverAddress}}:{{serverPort}}{{path}} {% else %} {{serverUri}}:{{serverPort}}{{path}} {% endif %} -p {{ protocol }} {{headers[presetHeaders]}} {% if body != blank %} --body {{ body }} {% endif %} {% if bodyFile != blank %} --bodyFile {{ bodyFile }} {% endif %}"
33 | options:
34 | requiredOperatingSystem: linux
35 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.HttpClient/Microsoft.Crank.Jobs.HttpClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | Latest
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.HttpClient/Runner.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Net.Http;
6 | using Jint;
7 |
8 | namespace Microsoft.Crank.Jobs.HttpClientClient
9 | {
10 | internal class Worker
11 | {
12 | public HttpMessageInvoker Invoker { get; set; }
13 | public SocketsHttpHandler Handler { get; set; }
14 | public Engine Script { get; set; }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.HttpClient/ScriptConsole.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Linq;
7 |
8 | namespace Microsoft.Crank.Jobs.HttpClientClient
9 | {
10 | internal class ScriptConsole
11 | {
12 | public bool HasErrors { get; private set; }
13 |
14 | public void Log(params object[] args)
15 | {
16 | Console.WriteLine(String.Join(" ", args.Select(x => x.ToString())));
17 | }
18 |
19 | public void Info(params object[] args)
20 | {
21 | Console.ForegroundColor = ConsoleColor.Green;
22 | Console.WriteLine(String.Join(" ", args.Select(x => x.ToString())));
23 | Console.ResetColor();
24 | }
25 |
26 | public void Warn(params object[] args)
27 | {
28 | Console.ForegroundColor = ConsoleColor.DarkYellow;
29 | Console.WriteLine(String.Join(" ", args.Select(x => x.ToString())));
30 | Console.ResetColor();
31 | }
32 |
33 | public void Error(params object[] args)
34 | {
35 | Console.ForegroundColor = ConsoleColor.Red;
36 | Console.WriteLine(String.Join(" ", args.Select(x => x.ToString())));
37 | Console.ResetColor();
38 |
39 | HasErrors = true;
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.HttpClient/Timeline.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using System.Net.Http;
8 |
9 | namespace Microsoft.Crank.Jobs.HttpClientClient
10 | {
11 | internal class Timeline
12 | {
13 | public Uri Uri { get; set; }
14 | public TimeSpan Delay { get; set; }
15 | public HttpMethod Method { get; set; }
16 | public Dictionary Headers { get; set; } = new Dictionary();
17 | public HttpContent HttpContent { get; set; }
18 | public string MimeType { get; set; }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.HttpClient/WorkerResult.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 |
7 | namespace Microsoft.Crank.Jobs.HttpClientClient
8 | {
9 | public class WorkerResult
10 | {
11 | public long AverageRps => (long)(TotalRequests / (Stopped - Started).TotalSeconds);
12 | public long TotalRequests => Status1xx + Status2xx + Status3xx + Status4xx + Status5xx;
13 | public double LatencyMeanMs { get; set; }
14 | public double LatencyMaxMs { get; set; }
15 | public long ThroughputBps { get; set; }
16 | public long DurationMs => (long)(Stopped - Started).TotalMilliseconds;
17 | public long BadResponses => Status1xx + Status4xx + Status5xx;
18 | public DateTime Started { get; set; }
19 | public DateTime Stopped { get; set; }
20 | public int Status1xx { get; set; }
21 | public int Status2xx { get; set; }
22 | public int Status3xx { get; set; }
23 | public int Status4xx { get; set; }
24 | public int Status5xx { get; set; }
25 | public int SocketErrors { get; set; }
26 | public int Connections { get; set; }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.HttpClient/scripts/log.js:
--------------------------------------------------------------------------------
1 | // Logs all request and their result
2 |
3 | function request(request, warmup) {
4 | console.info(`url: ${request.requestUri}`);
5 | }
6 |
7 | function response(response, warmup) {
8 | console.warn(`status: ${response.statusCode}`);
9 | }
10 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.HttpClient/scripts/script.js:
--------------------------------------------------------------------------------
1 | // Sample script file for HttpClient Crank client
2 |
3 | // This script has the same lifetime as the HttpClient thread.
4 |
5 | // Available properties:
6 | // - console
7 | // log(args)
8 | // info(args)
9 | // warn(args)
10 | // error(args)
11 | // hasErrors: bool
12 |
13 | function initialize(url, connections, warmup, duration, headers, version, quiet) {
14 |
15 | // Invoked before the client is created. Once per thread.
16 | // url: String
17 | // connections: Number
18 | // warmup: Number
19 | // duration: Number
20 | // headers: List (Array)
21 | // version: String
22 | // quiet: Boolean
23 | }
24 |
25 | function start(handler, requests) {
26 |
27 | // Invoked before the benchmark is started. Once per thread.
28 | // handler: System.Net.Http.SocketsHttpHandler
29 | // requests: List (Array)
30 |
31 | }
32 |
33 | function request(request, warmup) {
34 |
35 | // Invoked when a request is created.
36 | // request: System.Net.Http.HttpRequestMessage
37 | // warmup: bool
38 |
39 | }
40 |
41 | function response(response, warmup) {
42 |
43 | // Invoked when a request is created.
44 | // response: System.Net.Http.HttpResponseMessage
45 | // warmup: bool
46 |
47 | }
48 |
49 | function error(exception) {
50 |
51 | // Invoked when an error occurs
52 | // exception: System.Exception
53 |
54 | }
55 |
56 | function stop(handler) {
57 |
58 | // Invoked when a client is stopped.
59 | // handler: System.Net.Http.SocketsHttpHandler
60 |
61 | }
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.HttpClient/scripts/urls.js:
--------------------------------------------------------------------------------
1 | // Add custom requests dynamically
2 |
3 | function start(handler, requests) {
4 | requests.Clear();
5 | requests.Add(new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Get, "https://orchardcore.net"));
6 | }
7 |
8 | function request(request, warmup) {
9 | console.warn(`url: ${request.requestUri}`);
10 | }
11 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.K6/Microsoft.Crank.Jobs.K6.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | PreserveNewest
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.K6/k6.yml:
--------------------------------------------------------------------------------
1 | jobs:
2 | k6:
3 | source:
4 | repository: https://github.com/dotnet/crank.git
5 | branchOrCommit: main
6 | project: src/Microsoft.Crank.Jobs.K6/Microsoft.Crank.Jobs.K6.csproj
7 | sourceKey: k6
8 | noBuild: true
9 | readyStateText: K6 Client
10 | waitForExit: true
11 | variables:
12 | presetHeaders: none
13 | connections: 256
14 | warmup: 15
15 | duration: 15
16 | requests: 0
17 | rate: 0
18 | serverScheme: http
19 | serverAddress: localhost
20 | serverPort: 5000
21 | path:
22 | arguments: '--vus {{connections}} --warmup {{warmup}} --duration {{duration}} {% if requests != 0 %} --iterations {{requests}} {% endif %} {% if rate != 0 %} --rps {{ rate }} {% endif %} -e URL={{serverScheme}}://{{serverAddress}}:{{serverPort}}{{path}} -e HEADERS={{presetHeaders}}'
23 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.K6/scripts/default.js:
--------------------------------------------------------------------------------
1 | import http from 'k6/http';
2 | import { textSummary } from 'https://jslib.k6.io/k6-summary/0.1.0/index.js';
3 |
4 | const url = __ENV.URL;
5 | const presetHeaders = __ENV.HEADERS
6 |
7 | export const options = {
8 | summaryTrendStats: ['avg', 'min', 'max', 'p(50)', 'p(75)', 'p(90)', 'p(95)', 'p(99)']
9 | };
10 |
11 | export default function () {
12 |
13 | var headers = {
14 | none: {},
15 | plaintext: { 'Accept': 'text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7', 'Connection': 'keep-alive' },
16 | html: { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Connection': 'keep-alive' },
17 | json: { 'Accept': 'application/json,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7', 'Connection': 'keep-alive' },
18 | connectionclose: { 'Connection': 'close' },
19 | }
20 |
21 | const params = {
22 | // c.f. https://grafana.com/docs/k6/latest/javascript-api/k6-http/params/
23 | headers: headers[presetHeaders]
24 | };
25 |
26 | http.get(url, params);
27 | // console.log(url);
28 | }
29 |
30 | export function handleSummary(data) {
31 | // c.f. https://k6.io/docs/results-output/end-of-test/custom-summary/
32 | return {
33 | 'stdout': textSummary(data, { indent: ' ', enableColors: false }), // Show the text summary to stdout...
34 | 'summary.json': JSON.stringify(data) // and saves the raw data as JSON in a file
35 | };
36 | }
37 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.PipeliningClient/HttpResponse.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.Jobs.PipeliningClient
6 | {
7 | public enum HttpResponseState
8 | {
9 | StartLine,
10 | Headers,
11 | Body,
12 | ChunkedBody,
13 | Completed,
14 | Error
15 | }
16 |
17 | public class HttpResponse
18 | {
19 | public HttpResponseState State { get; set; } = HttpResponseState.StartLine;
20 | public int StatusCode { get; set; }
21 | public long ContentLength { get; set; }
22 | public long ContentLengthRemaining { get; set; }
23 | public bool HasContentLengthHeader { get; set; }
24 | public int LastChunkRemaining { get; set; }
25 |
26 | public void Reset()
27 | {
28 | State = HttpResponseState.StartLine;
29 | StatusCode = default;
30 | ContentLength = default;
31 | ContentLengthRemaining = default;
32 | HasContentLengthHeader = default;
33 | LastChunkRemaining = default;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.PipeliningClient/Microsoft.Crank.Jobs.PipeliningClient.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.PipeliningClient/SequenceReaderExtensions.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Buffers;
7 |
8 | namespace Microsoft.Crank.Jobs.PipeliningClient
9 | {
10 | public static class SequenceReaderExtensions
11 | {
12 | public static bool TryReadTo(this ref SequenceReader sequenceReader, out ReadOnlySpan span, ReadOnlySpan delimiter, bool advancePastDelimiter = true) where T : unmanaged, IEquatable
13 | {
14 | if (sequenceReader.TryReadTo(out ReadOnlySequence sequence, delimiter, advancePastDelimiter))
15 | {
16 | span = sequence.IsSingleSegment ? sequence.FirstSpan : sequence.ToArray();
17 | return true;
18 | }
19 | span = default;
20 | return false;
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.PipeliningClient/WorkerResult.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Collections;
6 | using System.Collections.Generic;
7 |
8 | namespace Microsoft.Crank.Jobs.PipeliningClient
9 | {
10 | public class WorkerResult
11 | {
12 | public int Status1xx { get; set; }
13 | public int Status2xx { get; set; }
14 | public int Status3xx { get; set; }
15 | public int Status4xx { get; set; }
16 | public int Status5xx { get; set; }
17 | public int SocketErrors { get; set; }
18 | public List StatusCodes { get; set; } = new();
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.PipeliningClient/pipelining.yml:
--------------------------------------------------------------------------------
1 | variables:
2 | headers:
3 | none: ''
4 | plaintext: '--header "Accept: text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7"'
5 | html: '--header "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"'
6 | json: '--header "Accept: application/json,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7"'
7 | connectionclose: '--header "Connection: close"'
8 | presetHeaders: none
9 |
10 | jobs:
11 | pipelining:
12 | source:
13 | repository: https://github.com/dotnet/crank.git
14 | branchOrCommit: main
15 | project: src/Microsoft.Crank.Jobs.PipeliningClient/Microsoft.Crank.Jobs.PipeliningClient.csproj
16 | readyStateText: Pipelining Client
17 | isConsoleApp: true
18 | waitForExit: true
19 | variables:
20 | connections: 256
21 | warmup: 15
22 | duration: 15
23 | pipeline: 1
24 | presetHeaders: none
25 | serverScheme: http
26 | serverAddress: localhost
27 | serverPort: 5000
28 | path: /
29 | customHeaders: [ ] # list of headers with the format: ': ', e.g. [ 'content-type: application/json' ]. In yml should look like: - "content-type: application/json"
30 | detailedResponseStats: false
31 | verboseConnectionLogs: false
32 | arguments: "--url \"{{serverScheme}}://{{serverAddress}}:{{serverPort}}{{path}}\" --connections {{connections}} --warmup {{warmup}} --duration {{duration}} --pipeline {{pipeline}} {{headers[presetHeaders]}} {% for h in customHeaders %}{% assign s = h | split : ':' %}--header \"{{ s[0] }}: {{ s[1] | strip }}\" {% endfor %} {% if detailedResponseStats == true %} --detailedResponseStats {% endif %} {% if verboseConnectionLogs == true %} --verboseConnectionLogs {% endif %}"
33 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.Wrk/Microsoft.Crank.Jobs.Wrk.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | PreserveNewest
15 |
16 |
17 | PreserveNewest
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.Wrk/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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Runtime.InteropServices;
7 | using System.Threading.Tasks;
8 |
9 | namespace Microsoft.Crank.Wrk
10 | {
11 | class Program
12 | {
13 | static async Task Main(string[] args)
14 | {
15 | if (Environment.OSVersion.Platform != PlatformID.Unix)
16 | {
17 | Console.WriteLine($"Platform not supported: {Environment.OSVersion.Platform}");
18 | return -1;
19 | }
20 |
21 | Console.WriteLine("WRK Client");
22 | Console.WriteLine("args: " + string.Join(' ', args));
23 |
24 | await WrkProcess.MeasureFirstRequest(args);
25 |
26 | await WrkProcess.DownloadWrkAsync();
27 | return await WrkProcess.RunAsync(args);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.Wrk/scripts/pipeline.lua:
--------------------------------------------------------------------------------
1 | init = function(args)
2 | local r = {}
3 | local depth = tonumber(args[1]) or 1
4 | for i=1,depth do
5 | r[i] = wrk.format()
6 | end
7 | req = table.concat(r)
8 | end
9 |
10 | request = function()
11 | return req
12 | end
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.Wrk2/Microsoft.Crank.Jobs.Wrk2.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | PreserveNewest
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Jobs.Wrk2/wrk2.yml:
--------------------------------------------------------------------------------
1 | # Warning
2 | # wrk2 might not return any value if the duration is too small (<15s)
3 |
4 | variables:
5 | headers:
6 | none: ''
7 | plaintext: '--header "Accept: text/plain,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7" --header "Connection: keep-alive"'
8 | html: '--header "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" --header "Connection: keep-alive"'
9 | json: '--header "Accept: application/json,text/html;q=0.9,application/xhtml+xml;q=0.9,application/xml;q=0.8,*/*;q=0.7" --header "Connection: keep-alive"'
10 | connectionclose: '--header "Connection: close"'
11 | presetHeaders: none
12 |
13 | jobs:
14 | wrk2:
15 | source:
16 | repository: https://github.com/dotnet/crank.git
17 | branchOrCommit: main
18 | project: src/Microsoft.Crank.Jobs.Wrk2/Microsoft.Crank.Jobs.Wrk2.csproj
19 | isConsoleApp: true
20 | waitForExit: true
21 | variables:
22 | connections: 256
23 | duration: 15
24 | timeout: # timeout in seconds (optional)
25 | warmup: 15
26 | threads: 32
27 | rate: 500
28 | serverScheme: http
29 | serverAddress: localhost
30 | serverPort: 5000
31 | path: /
32 | customHeaders: [ ] # list of headers with the format: ': ', e.g. [ 'content-type: application/json' ]
33 | arguments: "-c {{connections}} -d {{duration}}s -w {{warmup}}s {% if timeout != blank %} --timeout {{timeout}}s {% endif %} -t {{threads}} {{headers[presetHeaders]}} {% for h in customHeaders %}{% assign s = h | split : ':' %}--header \"{{ s[0] }}: {{ s[1] | strip }}\" {% endfor %} -R {{rate}} -L {% if serverUri == blank %} {{serverScheme}}://{{serverAddress}}:{{serverPort}}{{path}} {% else %} {{serverUri}}:{{serverPort}}{{path}} {% endif %}"
34 | options:
35 | requiredOperatingSystem: linux
36 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/Attachment.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.Models
6 | {
7 | public class Attachment
8 | {
9 | public string Filename { get; set; }
10 | public string TempFilename { get; set; }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/AttachmentViewModel.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using Microsoft.AspNetCore.Http;
6 |
7 | namespace Microsoft.Crank.Models
8 | {
9 | public class AttachmentViewModel
10 | {
11 | public int Id { get; set; }
12 | public string DestinationFilename { get; set; }
13 | public IFormFile Content { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/CommandDefinition.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Collections.Generic;
6 |
7 | namespace Microsoft.Crank.Models
8 | {
9 | public class CommandDefinition
10 | {
11 | public string Condition { get; set; } = "true";
12 | public ScriptType ScriptType { get; set; } = ScriptType.Powershell;
13 | public string Script { get; set; }
14 | public string FilePath { get; set; }
15 | public bool ContinueOnError { get; set; } = false;
16 | public List SuccessExitCodes { get; set; } = new List { 0 };
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/Database.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.Models
6 | {
7 | public enum Database
8 | {
9 | None,
10 | PostgreSql,
11 | SqlServer,
12 | MySql,
13 | MongoDb,
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/Dependency.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.Models
6 | {
7 | public class Dependency
8 | {
9 | public string Id { get; set; }
10 | public string[] Names { get; set; }
11 | public string RepositoryUrl { get; set; }
12 | public string Version { get; set; }
13 | public string CommitHash { get; set; }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/DotnetCounter.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.Models
6 | {
7 | public class DotnetCounter
8 | {
9 | ///
10 | /// Provider name, e.g., System.Runtime
11 | ///
12 | public string Provider { get; set; }
13 |
14 | ///
15 | /// Name of the counter, cpu-usage
16 | ///
17 | public string Name { get; set; }
18 |
19 | ///
20 | /// Name of the measurement, runtime/cpu-usage
21 | ///
22 | public string Measurement { get; set; }
23 |
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/DumpTypeOption.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.Models
6 | {
7 | ///
8 | /// The dump type determines the kinds of information that are collected from the process.
9 | ///
10 | public enum DumpTypeOption
11 | {
12 | Full, // The largest dump containing all memory including the module images.
13 |
14 | Heap, // A large and relatively comprehensive dump containing module lists, thread lists, all
15 | // stacks, exception information, handle information, and all memory except for mapped images.
16 |
17 | Mini, // A small dump containing module lists, thread lists, exception information and all stacks.
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/EnvironmentData.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Runtime.InteropServices;
7 |
8 | namespace Microsoft.Crank.Models
9 | {
10 | ///
11 | /// A model that stores information about the environment of the current process.
12 | /// This is useful when defining conditions for pre or post commands on the controller.
13 | ///
14 | public class EnvironmentData
15 | {
16 | private static readonly string platform = GetCurrentPlatform();
17 | private static readonly string architecture = RuntimeInformation.OSArchitecture.ToString();
18 |
19 | public string Platform => platform;
20 | public string Architecture => architecture;
21 |
22 | private static string GetCurrentPlatform()
23 | {
24 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
25 | {
26 | return "windows";
27 | }
28 | else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
29 | {
30 | return "linux";
31 | }
32 | else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
33 | {
34 | return "osx";
35 | }
36 | else
37 | {
38 | // Windows, Linux, and OSX are the only platforms that have predefined OSPlatform instances.
39 | return "other";
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/JobState.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.Models
6 | {
7 | public enum JobState
8 | {
9 | New, // The job was submitted
10 | Initializing, // The job is processed, the driver update it or submit attachments
11 | Waiting, // The job is ready to start, following a POST from the client to /start
12 | Starting, // The application has been started, the server is waiting for it to be responsive
13 | Running, // The application is running
14 | Failed,
15 | Stopping,
16 | Stopped,
17 | TraceCollecting, // The driver has requested the trace to be collected
18 | TraceCollected,
19 | Deleting,
20 | Deleted,
21 | NotSupported, // The job is not supported by the server
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/JobStatistics.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Collections.Generic;
6 |
7 | namespace Microsoft.Crank.Models
8 | {
9 | public class JobStatistics
10 | {
11 | public List Metadata = new List();
12 | public List Measurements = new List();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/Measurement.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using Newtonsoft.Json;
7 |
8 | namespace Microsoft.Crank.Models
9 | {
10 | public class Measurement
11 | {
12 | public const string Delimiter = "$$Delimiter$$";
13 |
14 | public DateTime Timestamp { get; set; }
15 | public string Name { get; set; }
16 | public object Value { get; set; }
17 |
18 | [JsonIgnore]
19 | public bool IsDelimiter => String.Equals(Name, Delimiter, StringComparison.OrdinalIgnoreCase);
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/MeasurementMetadata.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using Newtonsoft.Json;
6 | using Newtonsoft.Json.Converters;
7 |
8 | namespace Microsoft.Crank.Models
9 | {
10 | public class MeasurementMetadata
11 | {
12 | public string Source { get; set; }
13 | public string Name { get; set; }
14 |
15 | ///
16 | /// An operation used to aggregate the value across multiple sources returning the same measurement
17 | ///
18 | [JsonConverter(typeof(StringEnumConverter))]
19 | public Operation Reduce { get; set; }
20 |
21 | ///
22 | /// An operation used to aggregate the measures from the same source
23 | ///
24 | [JsonConverter(typeof(StringEnumConverter))]
25 | public Operation Aggregate { get; set; }
26 |
27 | public string ShortDescription { get; set; }
28 | public string LongDescription { get; set; }
29 |
30 | // A custom C# format string used for numerical values, e.g. "n0"
31 | public string Format { get; set; }
32 | }
33 |
34 | public enum Operation
35 | {
36 | First,
37 | Last,
38 | Avg,
39 | Sum,
40 | Median,
41 | Max,
42 | Min,
43 | Count,
44 | All,
45 | Delta // Difference between min and max of the set
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/Microsoft.Crank.Models.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Class to transfer data to/from the benchmark server.
5 | net8.0
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/OperatingSystem.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.Models
6 | {
7 | public enum OperatingSystem
8 | {
9 | Linux,
10 | Windows,
11 | OSX
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/Scheme.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.Models
6 | {
7 | public enum Scheme
8 | {
9 | Http,
10 | Https,
11 | H2,
12 | H2c
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/ScriptType.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.Models
6 | {
7 | public enum ScriptType
8 | {
9 | Batch,
10 | Bash,
11 | Powershell,
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.Models/WebHost.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.Models
6 | {
7 | public enum WebHost
8 | {
9 | KestrelSockets,
10 | KestrelLibuv,
11 | HttpSys,
12 | IISInProcess,
13 | IISOutOfProcess,
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.PullRequestBot/Command.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using Octokit;
6 |
7 | namespace Microsoft.Crank.PullRequestBot
8 | {
9 | public class Command
10 | {
11 | public PullRequest PullRequest { get; set; }
12 | public string[] Benchmarks { get; set; }
13 | public string[] Profiles { get; set; }
14 | public string[] Components { get; set; }
15 | public string Arguments { get; set; }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.PullRequestBot/Configuration.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 | using Newtonsoft.Json.Linq;
8 |
9 | namespace Microsoft.Crank.PullRequestBot
10 | {
11 | public class Configuration
12 | {
13 | public string Defaults { get; set; }
14 | public Dictionary Variables { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase);
15 | public Dictionary Components { get; set; } = new Dictionary(StringComparer.OrdinalIgnoreCase);
16 | public Dictionary Profiles { get; set; } = new Dictionary(StringComparer.OrdinalIgnoreCase);
17 | public Dictionary Benchmarks { get; set; } = new Dictionary(StringComparer.OrdinalIgnoreCase);
18 | }
19 |
20 | public class Profile
21 | {
22 | public string Description { get; set; }
23 | public string Arguments { get; set; }
24 | }
25 |
26 | public class Benchmark
27 | {
28 | public string Description { get; set; }
29 | public string Arguments { get; set; }
30 | public Dictionary Variables { get; } = new Dictionary(StringComparer.OrdinalIgnoreCase);
31 | }
32 |
33 | public class Build
34 | {
35 | public string Script { get; set; }
36 | public string Arguments { get; set; }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.PullRequestBot/JsonTypeResolver.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Globalization;
7 | using YamlDotNet.Core.Events;
8 | using YamlDotNet.Serialization;
9 |
10 | namespace Microsoft.Crank.PullRequestBot
11 | {
12 | /// Provides types resolution for YAML
13 | /// Without this booleans and numbers are parsed as strings
14 | public class JsonTypeResolver : INodeTypeResolver
15 | {
16 | public bool Resolve(NodeEvent nodeEvent, ref Type currentType)
17 | {
18 | if (nodeEvent is Scalar scalar && scalar.IsPlainImplicit)
19 | {
20 | if (decimal.TryParse(scalar.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out _))
21 | {
22 | currentType = typeof(decimal);
23 | return true;
24 | }
25 | else if (bool.TryParse(scalar.Value, out _))
26 | {
27 | currentType = typeof(bool);
28 | return true;
29 | }
30 | }
31 |
32 | return false;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.PullRequestBot/Microsoft.Crank.PullRequestBot.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | Runs benchmarks out of GitHub pull-requests.
6 | crank-pr
7 | crank-pr
8 | true
9 | true
10 | Exe
11 | Microsoft
12 | Microsoft.Crank.PullRequestBot
13 | 9.0
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | PreserveNewest
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.PullRequestBot/PullRequestBotException.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 |
7 | namespace Microsoft.Crank.PullRequestBot
8 | {
9 | public class PullRequestBotException : Exception
10 | {
11 | public PullRequestBotException(string message) : base(message)
12 | {
13 |
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.PullRequestBot/sample.config.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./pullrequestbot.schema.json",
3 | "defaults": "--config https://github.com/aspnet/Benchmarks/blob/main/build/azure.profile.yml?raw=true --application.framework net8.0 ", // --relay AZURE_RELAY
4 | "components": {
5 | "kestrel": {
6 | "script": "call ./src/Servers/Kestrel/build.cmd -noBuildJava -noBuildNodeJs -c release -noBuildNative /p:BuildIisNativeProjects=false",
7 | "arguments": "--application.options.outputFiles ./artifacts/bin/Microsoft.AspNetCore.Server.Kestrel/release/net8.0/"
8 | },
9 | "mvc": {
10 | "script": "REM Build MVC",
11 | "arguments": ""
12 | }
13 | },
14 | "profiles": {
15 | "aspnet-perf-lin": {
16 | "description": "INTEL/Linux 12 Cores",
17 | "arguments": "--profile aspnet-perf-lin"
18 | },
19 | "aspnet-perf-win": {
20 | "description": "INTEL/Windows 12 Cores",
21 | "arguments": "--profile aspnet-perf-win"
22 | }
23 | },
24 | "benchmarks": {
25 | "plaintext": {
26 | "description": "TechEmpower Plaintext Scenario - ASP.NET Middleware",
27 | "arguments": "--config https://raw.githubusercontent.com/aspnet/Benchmarks/main/scenarios/plaintext.benchmarks.yml --scenario plaintext"
28 | },
29 | "json": {
30 | "description": "TechEmpower JSON Scenario - ASP.NET Middleware",
31 | "arguments": "--config https://raw.githubusercontent.com/aspnet/Benchmarks/main/scenarios/json.benchmarks.yml --scenario json"
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.PullRequestBot/sample.config.yml:
--------------------------------------------------------------------------------
1 | # multi-line script used to build the project
2 | components:
3 | kestrel:
4 | script: |
5 | call ./src/Servers/Kestrel/build.cmd -noBuildJava -noBuildNodeJs -c release -noBuildNative /p:BuildIisNativeProjects=false
6 | REM call ./.dotnet/dotnet.exe build-server shutdown
7 | REM call taskkill /F /IM dotnet.exe # also kills main process in dotnet.exe
8 |
9 | arguments:
10 | --application.options.outputFiles ./artifacts/bin/Microsoft.AspNetCore.Server.Kestrel/release/net8.0/
11 | mvc:
12 | script: |
13 | echo FAKE MVC BUILD
14 | # ./src/Servers/Kestrel/build.sh -c release
15 | arguments:
16 | --application.options.outputFiles ./artifacts/bin/Microsoft.AspNetCore.MVC/release/net8.0/
17 |
18 | # default arguments that are always used on crank commands
19 | defaults: --config https://github.com/aspnet/Benchmarks/blob/main/build/azure.profile.yml?raw=true --application.framework net8.0 # --relay AZURE_RELAY
20 |
21 | # the first value is the default if none is specified
22 | profiles:
23 | aspnet-perf-lin:
24 | description: INTEL/Linux 12 Cores
25 | arguments: --profile aspnet-perf-lin
26 |
27 | aspnet-perf-win:
28 | description: INTEL/Windows 12 Cores
29 | arguments: --profile aspnet-perf-win
30 |
31 | benchmarks:
32 | plaintext:
33 | description: TechEmpower Plaintext Scenario - ASP.NET Middleware
34 | arguments: --config https://raw.githubusercontent.com/aspnet/Benchmarks/main/scenarios/plaintext.benchmarks.yml --scenario plaintext
35 |
36 | json:
37 | description: TechEmpower JSON Scenario - ASP.NET Middleware
38 | arguments: --config https://raw.githubusercontent.com/aspnet/Benchmarks/main/scenarios/json.benchmarks.yml --scenario json
39 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.RegressionBot/Configuration.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Collections.Generic;
6 |
7 | namespace Microsoft.Crank.RegressionBot
8 | {
9 | public class Configuration
10 | {
11 | public Dictionary Templates { get; set; } = new Dictionary();
12 | public List Sources { get; set; } = new List();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.RegressionBot/JsonTypeResolver.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Globalization;
7 | using YamlDotNet.Core.Events;
8 | using YamlDotNet.Serialization;
9 |
10 | namespace Microsoft.Crank.RegressionBot
11 | {
12 | /// Provides types resolution for YAML
13 | /// Without this booleans and numbers are parsed as strings
14 | public class JsonTypeResolver : INodeTypeResolver
15 | {
16 | public bool Resolve(NodeEvent nodeEvent, ref Type currentType)
17 | {
18 | if (nodeEvent is Scalar scalar && scalar.IsPlainImplicit)
19 | {
20 | if (decimal.TryParse(scalar.Value, NumberStyles.Any, CultureInfo.InvariantCulture, out var value))
21 | {
22 | currentType = typeof(decimal);
23 | return true;
24 | }
25 | else if (bool.TryParse(scalar.Value, out var b))
26 | {
27 | currentType = typeof(bool);
28 | return true;
29 | }
30 | }
31 |
32 | return false;
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.RegressionBot/Microsoft.Crank.RegressionBot.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | latest
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | PreserveNewest
37 |
38 |
39 | PreserveNewest
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.RegressionBot/Models/BenchmarksResult.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using Newtonsoft.Json.Linq;
7 |
8 | namespace Microsoft.Crank.RegressionBot.Models
9 | {
10 | public class BenchmarksResult
11 | {
12 | public int Id { get; set; }
13 | public bool Excluded { get; set; }
14 | public DateTimeOffset DateTimeUtc { get; set; }
15 | public string Session { get; set; }
16 | public string Scenario { get; set; }
17 | public string Description { get; set; }
18 | public string Document { get; set; }
19 |
20 | [MessagePack.IgnoreMember]
21 | private JObject _data;
22 |
23 | [MessagePack.IgnoreMember]
24 | [System.Text.Json.Serialization.JsonIgnore]
25 | public JObject Data => _data ??= JObject.Parse(Document);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.RegressionBot/Models/DependencyChange.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.RegressionBot.Models
6 | {
7 | public enum ChangeTypes
8 | {
9 | Diff,
10 | New,
11 | Removed
12 | }
13 |
14 | public class DependencyChange
15 | {
16 | ///
17 | /// e.g., "application", "load"
18 | ///
19 | public string Job { get; set; }
20 |
21 | ///
22 | /// e.g, "+kL3IPaqvdVHIVR8mUBvrw=="
23 | ///
24 | public string Id { get; set; }
25 |
26 | ///
27 | /// e.g, "Microsoft.AspNetCore.App"
28 | ///
29 | public string[] Names { get; set; }
30 |
31 | ///
32 | /// e.g., "https://github.com/dotnet/runtime"
33 | ///
34 | public string RepositoryUrl { get; set; }
35 |
36 | ///
37 | /// e.g., "6.0.0-preview.5.21228.5"
38 | ///
39 | public string PreviousVersion { get; set; }
40 |
41 | ///
42 | /// e.g., "6.0.0-preview.5.21228.5"
43 | ///
44 | public string CurrentVersion { get; set; }
45 |
46 | ///
47 | /// e.g., "52c1d0b9b72f09fa7cf1f491d1c147dc173b7d60"
48 | ///
49 | public string PreviousCommitHash { get; set; }
50 |
51 | ///
52 | /// e.g., "52c1d0b9b72f09fa7cf1f491d1c147dc173b7d60"
53 | ///
54 | public string CurrentCommitHash { get; set; }
55 |
56 | public ChangeTypes ChangeType { get; set; }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.RegressionBot/Models/Report.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Collections.Generic;
6 |
7 | namespace Microsoft.Crank.RegressionBot.Models
8 | {
9 | ///
10 | /// This class is used as a model for template reports.
11 | ///
12 | public class Report
13 | {
14 | public List Regressions { get; set; } = new List();
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.RegressionBot/Probe.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 | using System.Collections.Generic;
7 |
8 | namespace Microsoft.Crank.RegressionBot
9 | {
10 | public class Probe
11 | {
12 | // The JSON path to the value
13 | public string Path { get; set; }
14 |
15 | // The minimum value triggering an issue
16 | public double Threshold { get; set; } = 1;
17 |
18 | public ThresholdUnits Unit { get; set; } = ThresholdUnits.StDev;
19 | }
20 |
21 | public enum ThresholdUnits
22 | {
23 | None,
24 | StDev,
25 | Percent,
26 | Absolute
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.RegressionBot/Queries.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 | // See the LICENSE file in the project root for more information.
4 |
5 | namespace Microsoft.Crank.RegressionBot
6 | {
7 | public static class Queries
8 | {
9 | public const string Latest = """
10 | SELECT *
11 | FROM (
12 | SELECT TOP (10000) * -- Bounded to prevent from downloading too many records
13 | FROM [dbo].[{0}] -- Substitute table name
14 | ORDER BY [Id] DESC
15 | ) ORDERED
16 | WHERE [DateTimeUtc] >= @startDate
17 | """;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.RegressionBot/RegressionBotException.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System;
6 |
7 | namespace Microsoft.Crank.RegressionBot
8 | {
9 | public class RegressionBotException : Exception
10 | {
11 | public RegressionBotException(string message) : base(message)
12 | {
13 |
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.RegressionBot/Rule.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Collections.Generic;
6 | using System.Text.RegularExpressions;
7 |
8 | namespace Microsoft.Crank.RegressionBot
9 | {
10 | public class Rule
11 | {
12 | internal Regex IncludeRegex { get; set; }
13 | internal Regex ExcludeRegex { get; set; }
14 |
15 | public string Include { get; set; }
16 |
17 | public string Exclude { get; set; }
18 |
19 | ///
20 | /// Gets or sets the list of labels to assign to the issues
21 | ///
22 | public List Labels { get; set; } = new List();
23 |
24 | ///
25 | /// Gets or sets the list of users that are cced in the issue
26 | ///
27 | public List Owners = new List();
28 |
29 | ///
30 | /// Gets or sets whether the regressions on the scenario should be ignored
31 | ///
32 | public bool? IgnoreRegressions { get; set; }
33 | public bool? IgnoreErrors { get; set; }
34 | public bool? IgnoreFailures { get; set; }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/Microsoft.Crank.RegressionBot/SourceSection.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 | // See the LICENSE file in the project root for more information.
4 |
5 | using System.Collections.Generic;
6 |
7 | namespace Microsoft.Crank.RegressionBot
8 | {
9 | public class SourceSection
10 | {
11 | // Whether the bot checks if the benchmarks are still run regularly.
12 | public bool HealthCheck { get; set; } = false;
13 |
14 | // List of measurements that are checked against for regressions.
15 | public List Probes { get; set; } = new List();
16 |
17 | // Labels added to the issues created.
18 | public List Labels = new List();
19 |
20 | // Labels added to the issues created.
21 | public List Owners = new List();
22 |
23 | // The name of the template to use to render regressions for this source.
24 | public string Template { get; set; } = "";
25 |
26 | // The templated title of the issue. Leave empty for an auto-generated one.
27 | public string Title { get; set; } = "";
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/test/Microsoft.Crank.IntegrationTests/Microsoft.Crank.IntegrationTests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | Microsoft.Crank.IntegrationTests
6 | true
7 | true
8 | XUnit
9 | false
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/test/Microsoft.Crank.IntegrationTests/SkipOnLinuxAttribute.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 | using Xunit;
3 |
4 | namespace Microsoft.Crank.IntegrationTests
5 | {
6 | class SkipOnLinuxAttribute : FactAttribute
7 | {
8 | public SkipOnLinuxAttribute(string message = null)
9 | {
10 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
11 | {
12 | Skip = message ?? "Test ignored on Linux";
13 | }
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/test/Microsoft.Crank.IntegrationTests/SkipOnMacOsAttribute.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 | using Xunit;
3 |
4 | namespace Microsoft.Crank.IntegrationTests
5 | {
6 | class SkipOnMacOsAttribute : FactAttribute
7 | {
8 | public SkipOnMacOsAttribute(string message = null)
9 | {
10 | if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
11 | {
12 | Skip = message ?? "Test ignored on OSX";
13 | }
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/test/Microsoft.Crank.IntegrationTests/SkipOnWindowsAttribute.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.InteropServices;
2 | using Xunit;
3 |
4 | namespace Microsoft.Crank.IntegrationTests
5 | {
6 | class SkipOnWindowsAttribute : FactAttribute
7 | {
8 | public SkipOnWindowsAttribute(string message = null)
9 | {
10 | if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
11 | {
12 | Skip = message ?? "Test ignored on Windows";
13 | }
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/test/Microsoft.Crank.IntegrationTests/assets/hello.benchmarks.yml:
--------------------------------------------------------------------------------
1 | jobs:
2 | server:
3 | sources:
4 | hello:
5 | localFolder: '../hello'
6 | project: hello/hello.csproj
7 | readyStateText: Application started.
8 | bombardier:
9 | sources:
10 | local:
11 | # uploading the whole source folder since it requires other libraries
12 | localFolder: '../src'
13 | destinationFolder: ''
14 | project: Microsoft.Crank.Jobs.Bombardier/Microsoft.Crank.Jobs.Bombardier.csproj
15 | readyStateText: Bombardier Client
16 | waitForExit: true
17 | variables:
18 | connections: 256
19 | warmup: 3
20 | duration: 3
21 | requests: 0
22 | rate: 0
23 | transport: fasthttp # | http1 | http2
24 | serverScheme: http
25 | serverAddress: localhost
26 | serverPort: 5000
27 | customHeaders: [ ] # list of headers with the format: ': ', e.g. [ 'content-type: application/json' ]
28 | arguments: "-c {{connections}} -w {{warmup}} -d {{duration}} -n {{requests}} --insecure -l {% if rate != 0 %} --rate {{ rate }} {% endif %} {% if transport %} --{{ transport}} {% endif %} {{headers[presetHeaders]}} {% for h in customHeaders %}{% assign s = h | split : ':' %}--header \"{{ s[0] }}: {{ s[1] | strip }}\" {% endfor %} {{serverScheme}}://{{serverAddress}}:{{serverPort}}{{path}}"
29 |
30 | scenarios:
31 | hello:
32 | application:
33 | job: server
34 | load:
35 | job: bombardier
36 | variables:
37 | path: /
38 |
39 | profiles:
40 | local:
41 | variables:
42 | serverPort: 5000
43 | serverAddress: localhost
44 | jobs:
45 | application:
46 | endpoints:
47 | - http://localhost:5010
48 | load:
49 | endpoints:
50 | - http://localhost:5010
51 |
--------------------------------------------------------------------------------
/test/Microsoft.Crank.IntegrationTests/assets/multiclient.benchmarks.yml:
--------------------------------------------------------------------------------
1 | jobs:
2 | server:
3 | sources:
4 | hello:
5 | localFolder: '../hello'
6 | project: hello/hello.csproj
7 | readyStateText: Application started.
8 | bombardier:
9 | sources:
10 | local:
11 | # uploading the whole source folder since it requires other libraries
12 | localFolder: '../src'
13 | destinationFolder: ''
14 | project: Microsoft.Crank.Jobs.Bombardier/Microsoft.Crank.Jobs.Bombardier.csproj
15 | readyStateText: Bombardier Client
16 | waitForExit: true
17 | variables:
18 | connections: 256
19 | warmup: 3
20 | duration: 3
21 | requests: 0
22 | rate: 0
23 | transport: fasthttp # | http1 | http2
24 | serverScheme: http
25 | serverAddress: localhost
26 | serverPort: 5000
27 | arguments: "-c {{connections}} -w {{warmup}} -d {{duration}} -n {{requests}} --insecure -l {% if rate != 0 %} --rate {{ rate }} {% endif %} {% if transport %} --{{ transport}} {% endif %} {{headers[presetHeaders]}} {{serverScheme}}://{{serverAddress}}:{{serverPort}}{{path}}"
28 |
29 | scenarios:
30 | hello:
31 | application:
32 | job: server
33 | load:
34 | job: bombardier
35 | variables:
36 | path: /
37 |
38 | profiles:
39 | local:
40 | variables:
41 | serverPort: 5000
42 | serverAddress: localhost
43 | jobs:
44 | application:
45 | endpoints:
46 | - http://localhost:5010
47 | load:
48 | endpoints:
49 | - http://localhost:5010
50 | - http://localhost:5010
51 |
--------------------------------------------------------------------------------
/test/Microsoft.Crank.IntegrationTests/assets/post.benchmarks.yml:
--------------------------------------------------------------------------------
1 | jobs:
2 | post:
3 | sources:
4 | post:
5 | localFolder: '../post'
6 | project: post/post.csproj
7 | readyStateText: Application started.
8 | waitForExit: true
9 | arguments: '{{jobUrl}}' # http://localhost:5010/Jobs/1
10 | noClean: true
11 |
12 | scenarios:
13 | post:
14 | application:
15 | job: post
16 |
17 | profiles:
18 | local:
19 | jobs:
20 | application:
21 | endpoints:
22 | - http://localhost:5010
23 |
--------------------------------------------------------------------------------
/test/Microsoft.Crank.IntegrationTests/assets/scripts.benchmarks.yml:
--------------------------------------------------------------------------------
1 | results: # creates results from measurements
2 |
3 | - name: my/result
4 | description: Custom result (s)
5 | format: n2
6 |
7 | onResultsCreating:
8 | - |
9 | console.log("a default script")
10 |
11 | scripts:
12 |
13 | # records the current date and time as a custom property
14 | add_current_time: |
15 | benchmarks.properties["time"] = new Date().toISOString();
16 |
17 | onResultsCreated:
18 | - |
19 | benchmarks.jobs.application.results["my/result"] = 123;
20 |
--------------------------------------------------------------------------------
/test/Microsoft.Crank.RegressionBot.Tests/Microsoft.Crank.RegressionBot.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | Microsoft.Crank.RegressionBotTests
6 | true
7 | true
8 | XUnit
9 | false
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------