├── .editorconfig
├── .gitattributes
├── .github
├── CODEOWNERS
├── actions
│ └── oidc-auth-flow
│ │ └── action.yml
├── dependabot.yml
└── workflows
│ ├── TestCase.yml
│ ├── build-docs-verifier.yml
│ ├── codeql-analysis.yml
│ ├── dependabot-approve-and-automerge.yml
│ ├── dogfood.yml
│ ├── dotnet-build-validation.yml
│ ├── node-build-validation.yml
│ ├── quest-bulk.yml
│ └── quest.yml
├── .gitignore
├── .repoman.yml
├── CODE-OF-CONDUCT.md
├── DotNet.DocsTools
├── DotNet.DocsTools.csproj
├── GitHubClientServices
│ ├── GitHubAppClient.cs
│ ├── GitHubClient.cs
│ ├── GitHubClientBase.cs
│ ├── GraphQLPacket.cs
│ └── IGitHubClient.cs
├── GitHubObjects
│ ├── Actor.cs
│ ├── BankruptcyIssue.cs
│ ├── CloseBankruptyIssueMutation.cs
│ ├── DefaultBranch.cs
│ ├── FileHistory.cs
│ ├── GitHubLabel.cs
│ ├── GitHubObjectExtensions.cs
│ ├── IGitHubQueryResult.cs
│ ├── Issue.cs
│ ├── IssueOrPullRequest.cs
│ ├── PullRequestFiles.cs
│ ├── QuestIssue.cs
│ ├── QuestIssueOrPullRequest.cs
│ ├── QuestPullRequest.cs
│ ├── ResponseExtractors.cs
│ ├── SequesteredIssueMutation.cs
│ ├── SequesteredIssueOrPullRequestMutation.cs
│ ├── SequesteredPullRequestMutation.cs
│ ├── StoryPointSize.cs
│ └── WhatsNewPullRequest.cs
├── GraphQLQueries
│ ├── Common.cs
│ ├── EnumerationQuery.cs
│ ├── IGitHubMutation.cs
│ ├── LabeledIssueCounts.cs
│ ├── Mutation.cs
│ └── ScalarQuery.cs
├── OspoClientServices
│ ├── GitHubInfo.cs
│ ├── MicrosoftInfo.cs
│ ├── OspoClient.cs
│ ├── OspoException.cs
│ ├── OspoLink.cs
│ ├── OspoLinkSet.cs
│ └── OspoUnauthorizedException.cs
├── RESTQueries
│ └── PullRequestFilesRequest.cs
├── Serialization
│ └── JsonSerializerOptionsDefaults.cs
└── Utility
│ ├── CommandLineUtility.cs
│ ├── ContentScrubber.cs
│ ├── DateRange.cs
│ ├── EchoLogging.cs
│ ├── RawContentFromLocalFile.cs
│ └── SprintDateRange.cs
├── DotnetDocsToolsTests
├── DotnetDocsTools.Tests.csproj
├── FakeGitHubClient.cs
├── GraphQLProcessingTests
│ ├── ActorNodeTests.cs
│ ├── DefaultBranchTests.cs
│ ├── FilesInPRTests.cs
│ ├── PullRequestPerSprintTests.cs
│ ├── QuestIssueTests.cs
│ └── ScalarQueryTests.cs
├── RESTProcessingTests
│ └── PullRequestFilesQueryTests.cs
└── Utility
│ ├── ContentScrubberTests.cs
│ ├── DateRangeTests.cs
│ └── SprintDateRangeTests.cs
├── GitHub.QuerySandbox
├── GitHub.QuerySandbox.csproj
├── GlobalUsings.cs
├── Program.cs
├── Spinners
│ └── TimeTravelSpinner.cs
└── github-query-sandbox.sln
├── GitHub.RepositoryExplorer.Client
├── App.razor
├── Components
│ ├── ConfigureRepo.razor
│ ├── ConfigureRepo.razor.cs
│ └── ProgressIndicator.razor
├── Extensions
│ └── LocalStorageServiceExtensions.cs
├── GitHub.RepositoryExplorer.Client.csproj
├── GlobalUsings.cs
├── HttpClientNames.cs
├── Models
│ ├── IssueSummary.cs
│ ├── RepoLabels.cs
│ └── Repository.cs
├── Options
│ └── IssuesApiOptions.cs
├── Pages
│ ├── Areas.razor
│ ├── Areas.razor.cs
│ ├── Areas.razor.css
│ ├── ClassificationLineChart.razor
│ ├── ClassificationLineChart.razor.cs
│ ├── Index.razor
│ ├── PriorityLineChart.razor
│ ├── PriorityLineChart.razor.cs
│ ├── ProductLineChartJS.razor
│ ├── ProductLineChartJS.razor.cs
│ ├── SummaryChartJS.razor
│ └── SummaryChartJS.razor.cs
├── Program.cs
├── Properties
│ └── launchSettings.json
├── Services
│ ├── AppInMemoryStateService.cs
│ ├── DailyRecordFactory.cs
│ ├── IssueSnapshotsClient.cs
│ ├── IssuesByPriorityClassification.cs
│ ├── IssuesByPriorityClient.cs
│ ├── IssuesClient.cs
│ └── RespositoryLabelsClient.cs
├── Shared
│ ├── MainLayout.razor
│ ├── MainLayout.razor.css
│ ├── NavMenu.razor
│ └── NavMenu.razor.css
├── _Imports.razor
└── wwwroot
│ ├── appsettings.Development.json
│ ├── appsettings.json
│ ├── css
│ ├── app.css
│ ├── bootstrap
│ │ ├── bootstrap.min.css
│ │ └── bootstrap.min.css.map
│ └── open-iconic
│ │ ├── FONT-LICENSE
│ │ ├── ICON-LICENSE
│ │ ├── README.md
│ │ └── font
│ │ ├── css
│ │ └── open-iconic-bootstrap.min.css
│ │ └── fonts
│ │ ├── open-iconic.eot
│ │ ├── open-iconic.otf
│ │ ├── open-iconic.svg
│ │ ├── open-iconic.ttf
│ │ └── open-iconic.woff
│ ├── favicon.ico
│ ├── icon-192.png
│ └── index.html
├── GitHub.RepositoryExplorer.Functions
├── .gitignore
├── CaptureDailyIssueCountsFunction.cs
├── Configuration
│ ├── RepositoriesConfig.cs
│ └── RepositoryConfig.cs
├── GitHub.RepositoryExplorer.Functions.csproj
├── Properties
│ ├── ServiceDependencies
│ │ └── issue-statistics-functions - Zip Deploy
│ │ │ └── profile.arm.json
│ ├── serviceDependencies.json
│ └── serviceDependencies.local.json
├── README.md
├── Startup.cs
├── appsettings.Development.json
├── appsettings.json
└── host.json
├── GitHub.RepositoryExplorer.Models
├── DateOnlyConverter.cs
├── Extensions
│ ├── DailyRecordExtensions.cs
│ └── IssueMatrixExtensions.cs
├── GitHub.RepositoryExplorer.Models.csproj
├── IssueClassificationModel.cs
├── IssuesSnapshot.cs
├── RepositoryLabelConfig.cs
├── SnapshotKey.cs
└── dotnet-docs.json
├── GitHub.RepositoryExplorer.Services
├── GitHub.RepositoryExplorer.Services.csproj
├── IssueCountGenerator.cs
└── IssueCountStorage.cs
├── GitHub.RepositoryExplorer.WebApi
├── Controllers
│ ├── IssueSnapshotsController.cs
│ ├── IssuesController.cs
│ └── RepositoryLabelsController.cs
├── CorsPolicy.cs
├── GitHub.RepositoryExplorer.WebApi.csproj
├── GlobalUsings.cs
├── Program.cs
├── Properties
│ ├── launchSettings.json
│ ├── serviceDependencies.json
│ └── serviceDependencies.local.json
├── Services
│ └── IssueCountService.cs
├── appsettings.Development.json
└── appsettings.json
├── GitHub.RepositoryExplorer
└── GitHub.RepositoryExplorer.sln
├── IssueCloser
├── BulkCloseConfig.cs
├── CloseCriteria.cs
├── IssueCloser.csproj
├── IssueCloser
│ └── IssueCloser.sln
├── IssueSet.cs
├── Priorities.cs
├── Program.cs
└── bulkcloseconfig.json
├── LICENSE
├── LICENSE-CODE
├── PackageIndexer
├── CsvEntry.cs
├── CsvUtils.cs
├── DotnetPackageIndex.cs
├── FindProjectsWithDocs.ps1
├── NuGet
│ ├── NuGetFeed.cs
│ ├── NuGetFeeds.cs
│ └── NuGetStore.cs
├── PackageEntry.cs
├── PackageExtensions.cs
├── PackageFilter.cs
├── PackageIndexer.cs
├── PackageIndexer.csproj
├── PlatformPackageDefinition.cs
├── Program.cs
└── XmlEntryFormat.cs
├── README.md
├── RepoMan
├── .gitignore
├── .repoman.yml
├── Actions
│ ├── Assignees.cs
│ ├── CloseObject.cs
│ ├── Comment.cs
│ ├── File.cs
│ ├── Labels.cs
│ ├── Milestone.cs
│ ├── ProductTechLabels.cs
│ ├── Project.cs
│ ├── Reviewers.cs
│ └── Variables.cs
├── Checks
│ ├── CommentBody.cs
│ ├── DocMetadata.cs
│ ├── DocMetadataExists.cs
│ ├── DocNewMetadataExists.cs
│ ├── ForceFail.cs
│ ├── Group.cs
│ ├── ICheck.cs
│ ├── IsDraft.cs
│ ├── Query.cs
│ └── Variable.cs
├── Function1.cs
├── GithubCommand.cs
├── ILoggerExtensions.cs
├── IRunnerItem.cs
├── Program.cs
├── Properties
│ ├── ServiceDependencies
│ │ ├── repoman - Web Deploy
│ │ │ └── profile.arm.json
│ │ └── repoman - Zip Deploy
│ │ │ ├── appInsights1.arm.json
│ │ │ └── profile.arm.json
│ ├── serviceDependencies.json
│ ├── serviceDependencies.local.json
│ └── serviceDependencies.repoman - Zip Deploy.json
├── RepoMan.csproj
├── RepoMan.sln
├── RequestType.cs
├── Runner.cs
├── State.cs
├── Types.cs
├── Utilities.cs
├── YamlExtensions.cs
├── host.json
├── readme.md
└── state.json
├── RepoManChecker
├── CommandCheck.cs
├── CommandRun.cs
├── Program.cs
├── RepoManCheckerCLI.csproj
└── state-issues-opened.json
├── Sandbox
├── Program.cs
└── Sandbox.csproj
├── SmallRepo
├── Program.cs
├── SmallRepo.csproj
└── action.yml
├── ThirdPartyNotices.md
├── Whats-new
└── Whats-new.sln
├── WhatsNew.Cli
├── .vscode
│ └── extensions.json
├── CONTRIBUTING.md
├── Program.cs
├── README.md
├── WhatsNew.Cli.csproj
├── action.yml
└── nuget
│ └── images
│ └── docs-logo-ms.png
├── WhatsNew.Infrastructure.Tests
├── Models
│ └── PageGeneratorInputTests.cs
├── Services
│ ├── ConfigurationServiceTests.cs
│ └── SchemaValidationServiceTests.cs
├── WhatsNew.Infrastructure.Tests.csproj
├── assets
│ ├── MicrosoftDocs
│ │ ├── azure-devops-docs-pr.json
│ │ └── cpp-docs-pr.json
│ └── dotnet
│ │ ├── AspNetCore.Docs.json
│ │ └── docs.json
└── xunit.runner.json
├── WhatsNew.Infrastructure
├── Configuration
│ └── reposettings.schema.json
├── Constants.cs
├── Models
│ ├── DocLinkSettings.cs
│ ├── InclusionCriteria.cs
│ ├── Landing.cs
│ ├── NavigationDetails.cs
│ ├── PageGeneratorInput.cs
│ ├── RepositoryArea.cs
│ ├── RepositoryDetail.cs
│ ├── Toc.cs
│ └── WhatsNewConfiguration.cs
├── Services
│ ├── ConfigurationService.cs
│ ├── IndexUpdateService.cs
│ ├── PageGenerationService.cs
│ ├── SchemaValidationService.cs
│ └── TocUpdateService.cs
└── WhatsNew.Infrastructure.csproj
├── XmlDocConflictResolver
├── ConflictChecker.cs
├── Docs
│ ├── APIKind.cs
│ ├── DocsAPI.cs
│ ├── DocsAssemblyInfo.cs
│ ├── DocsCommentsContainer.cs
│ ├── DocsException.cs
│ ├── DocsMember.cs
│ ├── DocsMemberSignature.cs
│ ├── DocsParam.cs
│ ├── DocsRelated.cs
│ ├── DocsType.cs
│ ├── DocsTypeParam.cs
│ ├── DocsTypeSignature.cs
│ └── IDocsAPI.cs
├── IntelliSenseXml
│ ├── IntelliSenseXmlCommentsContainer.cs
│ ├── IntelliSenseXmlException.cs
│ ├── IntelliSenseXmlFile.cs
│ ├── IntelliSenseXmlMember.cs
│ ├── IntelliSenseXmlParam.cs
│ └── IntelliSenseXmlTypeParam.cs
├── Log.cs
├── Program.cs
├── Properties
│ └── launchSettings.json
├── XmlDocConflictResolver.csproj
└── XmlHelper.cs
├── actions
├── dependabot-bot
│ ├── .dockerignore
│ ├── .gitignore
│ ├── README.md
│ ├── action.yml
│ ├── dependabot-bot.sln
│ ├── packages-ignore.json
│ └── src
│ │ └── dependabot-bot
│ │ ├── Dockerfile
│ │ ├── Extensions
│ │ └── StringBuilderExtensions.cs
│ │ ├── GlobalUsings.cs
│ │ ├── Program.Regex.cs
│ │ ├── Program.Services.cs
│ │ ├── Program.cs
│ │ └── dependabot-bot.csproj
├── docs-verifier
│ ├── .editorconfig
│ ├── .gitignore
│ ├── Directory.Build.props
│ ├── Dockerfile
│ ├── MSDocsBuildVerifier.sln
│ ├── README.md
│ ├── action.yml
│ ├── docs
│ │ └── json-config-file.md
│ ├── eng
│ │ └── Settings.props
│ ├── nuget.config
│ ├── src
│ │ ├── ActionRunner
│ │ │ ├── ActionRunner.csproj
│ │ │ └── Program.cs
│ │ ├── BuildVerifier.IO.Abstractions
│ │ │ ├── BaseConfigurationReader.cs
│ │ │ ├── BaseMappedConfigurationReader.cs
│ │ │ └── BuildVerifier.IO.Abstractions.csproj
│ │ ├── GitHub
│ │ │ ├── GitHub.csproj
│ │ │ ├── GitHubPullRequest.cs
│ │ │ └── PullRequestFileExtensions.cs
│ │ ├── MarkdownLinksVerifier
│ │ │ ├── Configuration
│ │ │ │ ├── ConfigurationReader.cs
│ │ │ │ └── MarkdownLinksVerifierConfiguration.cs
│ │ │ ├── LinkClassifier
│ │ │ │ ├── Classifier.cs
│ │ │ │ └── LinkClassification.cs
│ │ │ ├── LinkValidator
│ │ │ │ ├── ILinkValidator.cs
│ │ │ │ ├── LinkValidatorCreator.cs
│ │ │ │ ├── LocalLinkValidator.cs
│ │ │ │ ├── MailtoLinkValidator.cs
│ │ │ │ ├── OnlineLinkValidator.cs
│ │ │ │ └── ValidationResult.cs
│ │ │ ├── MarkdownFilesAnalyzer.cs
│ │ │ └── MarkdownLinksVerifier.csproj
│ │ └── RedirectionVerifier
│ │ │ ├── DocfxConfiguration.cs
│ │ │ ├── DocfxConfigurationReader.cs
│ │ │ ├── NavigationOptions.cs
│ │ │ ├── OpenPublishingConfig.cs
│ │ │ ├── OpenPublishingConfigReader.cs
│ │ │ ├── OpenPublishingRedirectionReader.cs
│ │ │ ├── OpenPublishingRedirections.cs
│ │ │ ├── Redirection.cs
│ │ │ ├── RedirectionHelpers.cs
│ │ │ ├── RedirectionVerifier.csproj
│ │ │ ├── RedirectionsVerifier.cs
│ │ │ ├── WhatsNewConfiguration.cs
│ │ │ └── WhatsNewConfigurationReader.cs
│ ├── tests
│ │ ├── GitHub.UnitTests
│ │ │ ├── GitHub.UnitTests.csproj
│ │ │ └── PullRequestFileExtensionsTests.cs
│ │ └── MarkdownLinksVerifier
│ │ │ ├── ConfigurationTests
│ │ │ └── ConfigurationReaderTests.cs
│ │ │ ├── GlobalSuppressions.cs
│ │ │ ├── LinkClassifierTests.cs
│ │ │ ├── LinkValidatorTests
│ │ │ ├── LocalLinkValidatorTests.cs
│ │ │ ├── MailtoLinkValidatorTests.cs
│ │ │ └── Utilities
│ │ │ │ ├── FilesCollection.cs
│ │ │ │ └── Workspace.cs
│ │ │ └── MarkdownLinksVerifier.UnitTests.csproj
│ └── valid-test-cases
│ │ ├── MSDocsSpecific
│ │ ├── Includes
│ │ │ ├── aspnetcore.md
│ │ │ └── include.md
│ │ └── Includes2
│ │ │ ├── core
│ │ │ ├── compatibility
│ │ │ │ └── 2.1.md
│ │ │ └── tools
│ │ │ │ └── sdk-errors
│ │ │ │ └── netsdk1059.md
│ │ │ └── includes
│ │ │ └── dotnetclitoolreference.md
│ │ ├── MarkdownLinksVerifier
│ │ ├── test-query-parameters
│ │ │ ├── File.md
│ │ │ └── image.png
│ │ └── test1
│ │ │ ├── File1.md
│ │ │ └── folder
│ │ │ └── Name With Space.md
│ │ └── README.md
├── dotnet-version-updater
│ ├── action.yml
│ └── upgrade-projects.ps1
├── sequester
│ ├── .dockerignore
│ ├── .gitattributes
│ ├── .gitignore
│ ├── ImportIssues
│ │ ├── GlobalUsings.cs
│ │ ├── ImportIssues.csproj
│ │ └── Program.cs
│ ├── Quest2GitHub.Tests
│ │ ├── BuildExtendedPropertiesTests.cs
│ │ ├── GetIterationTests.cs
│ │ ├── GlobalUsings.cs
│ │ ├── ImportOptionsTests.cs
│ │ ├── Quest2GitHub.Tests.csproj
│ │ ├── QuestWorkItemTests.cs
│ │ ├── RawGitHubFileReaderTests.cs
│ │ └── quest-import.json
│ ├── Quest2GitHub.sln
│ ├── Quest2GitHub
│ │ ├── AzDoClientServices
│ │ │ ├── JsonPatchDocument.cs
│ │ │ └── QuestClient.cs
│ │ ├── Extensions
│ │ │ ├── ImportOptionsExtensions.cs
│ │ │ └── ServiceCollectionExtensions.cs
│ │ ├── GlobalUsings.cs
│ │ ├── Models
│ │ │ ├── IssueExtensions.cs
│ │ │ ├── QuestIteration.cs
│ │ │ ├── QuestWorkItem.cs
│ │ │ └── WorkItemProperties.cs
│ │ ├── Options
│ │ │ ├── ApiKeys.cs
│ │ │ ├── AzureDevOpsOptions.cs
│ │ │ ├── EnvironmentVariableReader.cs
│ │ │ ├── ImportOptions.cs
│ │ │ ├── LocalFileReader.cs
│ │ │ └── RawGitHubFileReader.cs
│ │ ├── Quest2GitHub.csproj
│ │ └── QuestGitHubService.cs
│ ├── README.md
│ └── action.yml
└── status-checker
│ ├── .eslintignore
│ ├── .eslintrc.json
│ ├── .gitattributes
│ ├── .gitignore
│ ├── .prettierignore
│ ├── README.md
│ ├── __tests__
│ ├── 3
│ │ └── three.md
│ ├── file-heading-extractor.test.ts
│ ├── main.test.ts
│ ├── no-heading.md
│ ├── pull-updater.test.ts
│ └── sample.md
│ ├── action.yml
│ ├── dist
│ ├── index.js
│ ├── index.js.map
│ ├── licenses.txt
│ └── sourcemap-register.js
│ ├── jest.config.js
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ ├── file-heading-extractor.ts
│ ├── main.ts
│ ├── pull-updater.ts
│ ├── status-checker.ts
│ ├── types
│ │ ├── ChangeType.ts
│ │ ├── FileChange.ts
│ │ ├── Mode.ts
│ │ ├── NodeOf.ts
│ │ ├── PageInfo.ts
│ │ ├── Pull.ts
│ │ ├── PullRequestDetails.ts
│ │ ├── PullRequestState.ts
│ │ └── WorkflowInput.ts
│ └── wait.ts
│ └── tsconfig.json
├── cleanrepo.Dockerfile
├── cleanrepo
├── CleanRepo.csproj
├── Extensions
│ └── TimeSpanExtensions.cs
├── GlobalSuppressions.cs
├── Options.cs
├── Program.cs
├── README.md
├── Redirect.cs
├── RedirectionFile.cs
├── Repo.cs
├── action.yml
├── appSettings.json
└── multiplexer.sh
├── docs-tools.sln
├── quest-config.json
├── sequester.Dockerfile
├── smalltest.Dockerfile
├── snippets5000
├── Get-MSBuildResults.ps1
├── Out-GithubActionStatus.ps1
├── PullRequestSimulations.Generators
│ ├── PullRequestSimulations.Generators.csproj
│ └── TestGenerator.cs
├── PullRequestSimulations
│ ├── LocalTests.cs
│ ├── PullRequestSimulations.csproj
│ ├── Usings.cs
│ ├── data.json
│ └── snippets
│ │ ├── bad
│ │ ├── lots-o-projects
│ │ │ ├── extensions
│ │ │ │ ├── LinqExtensions.cs
│ │ │ │ ├── Program.cs
│ │ │ │ └── linq.csproj
│ │ │ ├── linq-snippets.sln
│ │ │ └── partition_not_in_sln
│ │ │ │ ├── Program.cs
│ │ │ │ └── partition.csproj
│ │ ├── nullablepatternmatching
│ │ │ └── Program.cs
│ │ ├── patternmatching
│ │ │ ├── Program.cs
│ │ │ ├── childfolder
│ │ │ │ ├── Program.cs
│ │ │ │ └── other.csproj
│ │ │ └── patternmatching.csproj
│ │ ├── samefolder
│ │ │ ├── Program.cs
│ │ │ ├── project1.csproj
│ │ │ └── project2.vbproj
│ │ └── sln_no_proj
│ │ │ ├── file.sln
│ │ │ └── some_code
│ │ │ ├── Planet.cs
│ │ │ ├── PlanetType.cs
│ │ │ ├── Program.DistinctBy.cs
│ │ │ ├── Program.ExceptBy.cs
│ │ │ ├── Program.IntersectBy.cs
│ │ │ ├── Program.UnionBy.cs
│ │ │ └── Program.cs
│ │ └── good
│ │ ├── deeper-path
│ │ ├── finished
│ │ │ └── toll-calculator
│ │ │ │ ├── ExternalSystems.cs
│ │ │ │ ├── Program.cs
│ │ │ │ ├── TollCalculator.cs
│ │ │ │ └── toll-calculator.csproj
│ │ ├── start
│ │ │ └── toll-calculator
│ │ │ │ ├── ExternalSystems.cs
│ │ │ │ ├── Program.cs
│ │ │ │ └── toll-calculator.csproj
│ │ └── three_projs
│ │ │ ├── cpp
│ │ │ ├── MyForm.cpp
│ │ │ ├── MyForm.h
│ │ │ ├── MyForm.resx
│ │ │ ├── Student.h
│ │ │ ├── Subject.h
│ │ │ ├── TextBook.h
│ │ │ ├── project.vcxproj
│ │ │ ├── project.vcxproj.filters
│ │ │ └── snippets.5000.json
│ │ │ ├── cs
│ │ │ ├── Form1.Designer.cs
│ │ │ ├── Form1.cs
│ │ │ ├── Form1.resx
│ │ │ ├── Program.cs
│ │ │ ├── Student.cs
│ │ │ ├── Subject.cs
│ │ │ ├── TextBook.cs
│ │ │ ├── project.csproj
│ │ │ └── snippets.5000.json
│ │ │ └── vb
│ │ │ ├── App.config
│ │ │ ├── Form1.Designer.vb
│ │ │ ├── Form1.resx
│ │ │ ├── Form1.vb
│ │ │ ├── My Project
│ │ │ ├── Application.Designer.vb
│ │ │ ├── Application.myapp
│ │ │ ├── AssemblyInfo.vb
│ │ │ ├── Resources.Designer.vb
│ │ │ ├── Resources.resx
│ │ │ ├── Settings.Designer.vb
│ │ │ └── Settings.settings
│ │ │ ├── Student.vb
│ │ │ ├── Subject.vb
│ │ │ ├── TextBook.vb
│ │ │ └── project.vbproj
│ │ ├── normal
│ │ ├── asandis
│ │ │ ├── Program.cs
│ │ │ └── asandis.csproj
│ │ ├── csharp_project
│ │ │ ├── Program.cs
│ │ │ ├── app1.csproj
│ │ │ └── snippets.5000.json
│ │ ├── deleted_code
│ │ │ ├── snippets.5000.json
│ │ │ └── some-other-artifact.txt
│ │ ├── nullablepatternmatching
│ │ │ ├── Program.cs
│ │ │ └── nullablepatternmatching.csproj
│ │ ├── patternmatching
│ │ │ ├── Program.cs
│ │ │ └── patternmatching.csproj
│ │ └── vb_project
│ │ │ ├── Program.vb
│ │ │ └── app1.vbproj
│ │ └── solutions
│ │ ├── lots-o-projects
│ │ ├── extensions
│ │ │ ├── LinqExtensions.cs
│ │ │ ├── Program.cs
│ │ │ └── linq.csproj
│ │ ├── linq-snippets.sln
│ │ ├── partition
│ │ │ ├── Program.cs
│ │ │ └── partition.csproj
│ │ ├── projection
│ │ │ ├── Program.ZipResult.cs
│ │ │ ├── Program.ZipTriple.cs
│ │ │ ├── Program.ZipTuple.cs
│ │ │ ├── Program.cs
│ │ │ └── projection.csproj
│ │ └── set-operators
│ │ │ ├── Planet.cs
│ │ │ ├── PlanetType.cs
│ │ │ ├── Program.DistinctBy.cs
│ │ │ ├── Program.ExceptBy.cs
│ │ │ ├── Program.IntersectBy.cs
│ │ │ ├── Program.UnionBy.cs
│ │ │ ├── Program.cs
│ │ │ └── set-operators.csproj
│ │ ├── single-project
│ │ ├── linq-snippets.sln
│ │ └── set-operators
│ │ │ ├── Planet.cs
│ │ │ ├── PlanetType.cs
│ │ │ ├── Program.DistinctBy.cs
│ │ │ ├── Program.ExceptBy.cs
│ │ │ ├── Program.IntersectBy.cs
│ │ │ ├── Program.UnionBy.cs
│ │ │ ├── Program.cs
│ │ │ └── set-operators.csproj
│ │ └── sln_odd_proj
│ │ ├── file.sln
│ │ └── some_code
│ │ ├── Planet.cs
│ │ ├── PlanetType.cs
│ │ ├── Program.DistinctBy.cs
│ │ ├── Program.ExceptBy.cs
│ │ ├── Program.IntersectBy.cs
│ │ ├── Program.UnionBy.cs
│ │ ├── Program.cs
│ │ └── project1.proj
└── Snippets5000
│ ├── DiscoveryResult.cs
│ ├── Extensions.cs
│ ├── FullBuildProjectList.cs
│ ├── Program.cs
│ ├── Properties
│ └── launchSettings.json
│ ├── PullRequestProcessor.cs
│ ├── PullRequestSimulationsHelpers
│ ├── ChangeItem.cs
│ ├── ChangeItemType.cs
│ ├── ExpectedResult.cs
│ └── PullRequest.cs
│ ├── Snippets5000.csproj
│ ├── Snippets5000.sln
│ ├── SnippetsConfigFile.cs
│ └── TestingProjectList.cs
└── whatsnew.Dockerfile
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set the default behavior, in case people don't have core.autocrlf set.
2 | * text=auto
3 |
4 | # Explicitly declare text files you want to always be normalized and converted
5 | # to native line endings on checkout.
6 | *.c text
7 | *.h text
8 |
9 | # Declare files that will always have CRLF line endings on checkout.
10 | *.sln text eol=crlf
11 |
12 | # Denote all files that are truly binary and should not be modified.
13 | *.png binary
14 | *.jpg binary
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 |
2 | * @dotnet/docs
3 |
4 | actions/dependabot-bot/ @IEvangelist
5 | actions/docs-verifier/ @BillWagner @IEvangelist
6 | actions/dotnet-version-updater/ @IEvangelist
7 | actions/sequester/ @BillWagner
8 | actions/status-checker/ @gewarren
9 | cleanrepo/ @gewarren
10 | DotNet.DocsTools/ @IEvangelist @BillWagner
11 | DotNet.DocsToolsTests/ @IEvangelist @BillWagner
12 | GitHub.QuerySandbox/ @BillWagner
13 | GitHub.RepositoryExplorer/ @BillWagner
14 | GitHub.RepositoryExplorer.Client/ @BillWagner
15 | GitHub.RepositoryExplorer.Functions/ @BillWagner
16 | GitHub.RepositoryExplorer.Models/ @BillWagner
17 | GitHub.RepositoryExplorer.Services/ @BillWagner
18 | GitHub.RepositoryExplorer.WebApi/ @BillWagner
19 | IssueCloser/ @BillWagner
20 | PackageIndexer/ @gewarren
21 | RepoMan/ @adegeo
22 | RepoManChecker/ @adegeo
23 | snippets5000/ @adegeo @BillWagner
24 | Whats-new/ @BillWagner
25 | WhatsNew.Cli/ @BillWagner
26 | WhatsNew.Infrastructure/ @BillWagner
27 | WhatsNew.Infrastructure.Tests/ @BillWagner
28 | XmlDocConflictResolver/ @gewarren
29 |
30 |
--------------------------------------------------------------------------------
/.github/actions/oidc-auth-flow/action.yml:
--------------------------------------------------------------------------------
1 | name: Azure OIDC auth flow
2 | description: "Azure OpenID Connect authentication flow"
3 |
4 | inputs:
5 | client-id:
6 | description: "The Azure AD application client ID"
7 | required: true
8 | tenant-id:
9 | description: "The Azure AD tenant ID"
10 | required: true
11 | audience:
12 | description: "The audience for the access token"
13 | required: true
14 |
15 | outputs:
16 | access-token:
17 | description: "The Azure OIDC bearer access token"
18 | value: ${{ steps.api-access.outputs.AZURE_ACCESS_TOKEN }}
19 |
20 | runs:
21 | using: "composite"
22 | steps:
23 | - name: Azure OpenID Connect
24 | uses: azure/login@v2
25 | with:
26 | client-id: ${{ inputs.client-id }}
27 | tenant-id: ${{ inputs.tenant-id }}
28 | audience: ${{ inputs.audience }}
29 | allow-no-subscriptions: true
30 |
31 | - name: OSMP API access
32 | id: api-access
33 | shell: bash
34 | run: |
35 | TOKEN=$(az account get-access-token --query 'accessToken' -o tsv --resource ${{ inputs.audience }})
36 | echo "AZURE_ACCESS_TOKEN=$(echo $TOKEN)" >> $GITHUB_OUTPUT
37 |
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | # GitHub Actions
4 | - package-ecosystem: "github-actions"
5 | directory: "/"
6 | schedule:
7 | interval: "weekly"
8 | day: "wednesday"
9 | open-pull-requests-limit: 10
10 | # NuGet packages
11 | - package-ecosystem: "nuget"
12 | directory: "/"
13 | schedule:
14 | interval: "weekly"
15 | day: "wednesday"
16 | open-pull-requests-limit: 5
17 | groups:
18 | dotnet:
19 | patterns:
20 | - "*"
21 | # NPM packages
22 | - package-ecosystem: "npm"
23 | directory: "/"
24 | schedule:
25 | interval: "weekly"
26 | day: "wednesday"
27 | open-pull-requests-limit: 5
28 | groups:
29 | npm:
30 | patterns:
31 | - "*"
32 | # Dockerfiles
33 | - package-ecosystem: "docker"
34 | directory: "/"
35 | schedule:
36 | interval: "weekly"
37 | day: "wednesday"
38 | open-pull-requests-limit: 5
39 | groups:
40 | docker:
41 | patterns:
42 | - "*"
43 |
--------------------------------------------------------------------------------
/.github/workflows/dependabot-approve-and-automerge.yml:
--------------------------------------------------------------------------------
1 | name: Dependabot auto-approve and auto-merge
2 | on: pull_request
3 |
4 | permissions:
5 | contents: write
6 | pull-requests: write
7 |
8 | jobs:
9 | dependabot:
10 | runs-on: ubuntu-latest
11 | if: ${{ github.actor == 'dependabot[bot]' && github.repository_owner == 'dotnet' }}
12 | steps:
13 | - name: Dependabot metadata
14 | id: metadata
15 | uses: dependabot/fetch-metadata@v2
16 | with:
17 | github-token: "${{ secrets.GITHUB_TOKEN }}"
18 | - name: Approve a PR
19 | run: gh pr review --approve "$PR_URL"
20 | env:
21 | PR_URL: ${{github.event.pull_request.html_url}}
22 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
23 | - name: Enable auto-merge for Dependabot PRs
24 | run: gh pr merge --auto --merge "$PR_URL"
25 | env:
26 | PR_URL: ${{github.event.pull_request.html_url}}
27 | GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
28 |
--------------------------------------------------------------------------------
/.github/workflows/dogfood.yml:
--------------------------------------------------------------------------------
1 | name: Dogfood docs-verifier
2 | on: pull_request
3 |
4 | jobs:
5 | validate_links:
6 | name: MSDocs verifier
7 | runs-on: ubuntu-latest
8 |
9 | steps:
10 | - name: Checkout the repository
11 | uses: actions/checkout@main
12 |
13 | - name: Docs verifier
14 | env:
15 | GITHUB_PR_NUMBER: ${{ github.event.pull_request.number }}
16 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17 | uses: ./actions/docs-verifier
18 |
--------------------------------------------------------------------------------
/.github/workflows/node-build-validation.yml:
--------------------------------------------------------------------------------
1 | name: node build and test
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | paths:
7 | - 'actions/status-checker/**' # Only run for TypeScript action updates
8 | pull_request:
9 | branches: [ main ]
10 | paths:
11 | - 'actions/status-checker/**' # Only run for TypeScript action updates
12 |
13 | jobs:
14 | build:
15 | name: build
16 | runs-on: ubuntu-latest
17 | steps:
18 | - uses: actions/checkout@main
19 | - name: Use Node.js 18
20 | uses: actions/setup-node@main
21 | with:
22 | node-version: 18
23 | cache: 'npm'
24 | cache-dependency-path: ./actions/status-checker/package-lock.json
25 | - run: |
26 | cd ./actions/status-checker/
27 | npm ci
28 | npm run build --if-present
29 | npm test
30 |
--------------------------------------------------------------------------------
/.repoman.yml:
--------------------------------------------------------------------------------
1 | revision: 1
2 | schema-version: 5
3 | owner-ms-alias: adegeo
4 |
5 | config:
6 | DocMetadata:
7 | Headers:
8 | - ["---", "#### "]
9 |
10 | ParserRegex: "^\\* (.*): (.*)$"
11 |
12 | ContentUrlRegex:
13 | - "### Page URL\n\n(.*)"
14 |
15 | issues:
16 |
17 | labeled:
18 |
19 | # Temporary label to mark issues as updated for Quest. The label is instantly removed
20 | - check:
21 | - type: query
22 | value: "length(Issue.Labels[?Name == ':world_map: mapQUEST']) != `0`"
23 | pass:
24 | - labels-remove: [":world_map: mapQUEST"]
25 |
26 | projects_v2_item:
27 |
28 | reordered:
29 |
30 | - labels-add: [":world_map: mapQUEST"]
31 |
32 | edited:
33 |
34 | - check:
35 | - type: query
36 | value: "EventPayload.changes.field_value.field_name == 'Priority' || EventPayload.changes.field_value.field_name == 'Size'"
37 | pass:
38 | - labels-add: [":world_map: mapQUEST"]
39 |
--------------------------------------------------------------------------------
/CODE-OF-CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Code of conduct
2 |
3 | This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community.
4 |
5 | For more information, see the [.NET Foundation Code of Conduct](https://dotnetfoundation.org/code-of-conduct).
6 |
7 |
--------------------------------------------------------------------------------
/DotNet.DocsTools/DotNet.DocsTools.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | 2.2.0.0
8 | 2.2.0.0
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/DotNet.DocsTools/GitHubClientServices/GitHubClient.cs:
--------------------------------------------------------------------------------
1 | using System.Net.Http.Headers;
2 |
3 | namespace DotNetDocs.Tools.GitHubCommunications;
4 | public sealed class GitHubClient : GitHubClientBase, IGitHubClient, IDisposable
5 | {
6 | internal GitHubClient(string token)
7 | {
8 | Console.WriteLine("Using default GitHub PAT token.");
9 | SetAuthorizationHeader(new AuthenticationHeaderValue("Token", token));
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/DotNet.DocsTools/GitHubClientServices/GraphQLPacket.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 |
3 | namespace DotNetDocs.Tools.GitHubCommunications;
4 |
5 | ///
6 | /// This basic class represents a GraphQL post packet.
7 | ///
8 | ///
9 | /// This class represents a query packet. It has the shape expected
10 | /// for a GraphQL query.
11 | ///
12 | public class GraphQLPacket
13 | {
14 | ///
15 | /// The query or mutation string.
16 | ///
17 | public string query { get; set; } = "";
18 |
19 | ///
20 | /// The dictionary of variables for the query.
21 | ///
22 | public IDictionary variables { get; } = new Dictionary();
23 |
24 | ///
25 | /// Convert this object to JSON.
26 | ///
27 | /// The minified JSON for this object.
28 | public string ToJsonText() => JsonSerializer.Serialize(this);
29 | }
30 |
--------------------------------------------------------------------------------
/DotNet.DocsTools/GitHubObjects/Issue.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 |
3 | namespace DotNet.DocsTools.GitHubObjects;
4 |
5 | public abstract record Issue : IssueOrPullRequest
6 | {
7 | public Issue(JsonElement element) : base(element)
8 | {
9 | Body = ResponseExtractors.GetBodyValue(element);
10 | }
11 |
12 | ///
13 | /// The body of the issue
14 | ///
15 | ///
16 | /// This is the body of the issue as markdown text.
17 | ///
18 | public string? Body { get; }
19 | }
20 |
--------------------------------------------------------------------------------
/DotNet.DocsTools/GitHubObjects/SequesteredIssueMutation.cs:
--------------------------------------------------------------------------------
1 | using DotNet.DocsTools.GraphQLQueries;
2 | using DotNetDocs.Tools.GitHubCommunications;
3 |
4 | namespace DotNet.DocsTools.GitHubObjects;
5 |
6 | ///
7 | /// The mutation to sequester an issue.
8 | ///
9 | ///
10 | /// This performs three distinct actions in order. First, the "request" label is removed. Second,
11 | /// the body text is updated to add a link to the AzDo work item. Third, the "sequestered label
12 | /// is added.
13 | ///
14 | public class SequesteredIssueMutation : SequesteredIssueOrPullRequestMutation, IGitHubMutation
15 | {
16 | ///
17 | /// Construct the mutation packet
18 | ///
19 | /// The set of variables to use.
20 | /// The packet, including all variables.
21 | public static GraphQLPacket GetMutationPacket(SequesterVariables variables) =>
22 | GetMutationPacket(variables, true);
23 | }
24 |
--------------------------------------------------------------------------------
/DotNet.DocsTools/GitHubObjects/SequesteredPullRequestMutation.cs:
--------------------------------------------------------------------------------
1 | using DotNet.DocsTools.GraphQLQueries;
2 | using DotNetDocs.Tools.GitHubCommunications;
3 |
4 | namespace DotNet.DocsTools.GitHubObjects;
5 | public class SequesteredPullRequestMutation : SequesteredIssueOrPullRequestMutation, IGitHubMutation
6 | {
7 | ///
8 | /// Construct the mutation packet
9 | ///
10 | /// The set of variables to use.
11 | /// The packet, including all variables.
12 | public static GraphQLPacket GetMutationPacket(SequesterVariables variables) =>
13 | GetMutationPacket(variables, false);
14 | }
15 |
--------------------------------------------------------------------------------
/DotNet.DocsTools/GraphQLQueries/Common.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 |
3 | namespace DotNetDocs.Tools.GraphQLQueries;
4 |
5 | public static class Common
6 | {
7 | public static JsonElement Descendent(this JsonElement element, IEnumerable path)
8 | {
9 | foreach (var item in path)
10 | {
11 | if ((element.ValueKind == JsonValueKind.Null) || (!element.TryGetProperty(item, out element)))
12 | return default;
13 | }
14 | return element;
15 | }
16 |
17 | public static JsonElement Descendent(this JsonElement element, params string[] path)
18 | {
19 | foreach (var item in path)
20 | {
21 | if ((element.ValueKind == JsonValueKind.Null) || (!element.TryGetProperty(item, out element)))
22 | return default;
23 | }
24 | return element;
25 | }
26 |
27 | public static (bool hasNext, string endCursor) NextPageInfo(this JsonElement pageInfoNode) =>
28 | (pageInfoNode.Descendent("pageInfo", "hasNextPage").GetBoolean(),
29 | pageInfoNode.Descendent("pageInfo", "endCursor").GetString() ?? string.Empty);
30 | }
31 |
--------------------------------------------------------------------------------
/DotNet.DocsTools/GraphQLQueries/IGitHubMutation.cs:
--------------------------------------------------------------------------------
1 | using DotNetDocs.Tools.GitHubCommunications;
2 |
3 | namespace DotNet.DocsTools.GraphQLQueries;
4 |
5 |
6 | ///
7 | /// Interface that collaborates with the class to
8 | /// perform a GitHub mutation.
9 | ///
10 | /// The class that performs a specific mutation.
11 | /// A record that contains the types for the variables in the GraphQL packet.
12 | public interface IGitHubMutation where TMutation : IGitHubMutation
13 | {
14 | ///
15 | /// Return the GraphQL packet for the mutation.
16 | ///
17 | /// A record that defines the variables.
18 | /// The query packet.
19 | public abstract static GraphQLPacket GetMutationPacket(TVariables variables);
20 | }
21 |
--------------------------------------------------------------------------------
/DotNet.DocsTools/OspoClientServices/GitHubInfo.cs:
--------------------------------------------------------------------------------
1 | // Taken from https://github.com/dotnet/org-policy/tree/main/src/Microsoft.DotnetOrg.Ospo
2 |
3 | namespace Microsoft.DotnetOrg.Ospo;
4 |
5 | #pragma warning disable CS8618 // This is a serialized type.
6 | public sealed class GitHubInfo
7 | {
8 | public int Id { get; set; }
9 | public string Login { get; set; }
10 | public List Organizations { get; set; }
11 | }
12 | #pragma warning restore CS8618
13 |
14 |
--------------------------------------------------------------------------------
/DotNet.DocsTools/OspoClientServices/MicrosoftInfo.cs:
--------------------------------------------------------------------------------
1 | // Taken from https://github.com/dotnet/org-policy/tree/main/src/Microsoft.DotnetOrg.Ospo
2 |
3 | namespace Microsoft.DotnetOrg.Ospo;
4 |
5 | #pragma warning disable CS8618 // This is a serialized type.
6 | public sealed class MicrosoftInfo
7 | {
8 | public string Alias { get; set; }
9 | public string PreferredName { get; set; }
10 | public string UserPrincipalName { get; set; }
11 | public string EmailAddress { get; set; }
12 | public string Id { get; set; }
13 | }
14 | #pragma warning restore CS8618
15 |
16 |
--------------------------------------------------------------------------------
/DotNet.DocsTools/OspoClientServices/OspoException.cs:
--------------------------------------------------------------------------------
1 | // Taken from https://github.com/dotnet/org-policy/tree/main/src/Microsoft.DotnetOrg.Ospo
2 |
3 | using System.Net;
4 |
5 | namespace Microsoft.DotnetOrg.Ospo;
6 |
7 | [Serializable]
8 | public class OspoException : Exception
9 | {
10 | public OspoException()
11 | {
12 | }
13 |
14 | public OspoException(string? message)
15 | : base(message)
16 | {
17 | }
18 |
19 | public OspoException(string? message, Exception? inner)
20 | : base(message, inner)
21 | {
22 | }
23 |
24 | public OspoException(string? message, HttpStatusCode code)
25 | : this(message)
26 | {
27 | Code = code;
28 | }
29 |
30 | public HttpStatusCode Code { get; }
31 | }
--------------------------------------------------------------------------------
/DotNet.DocsTools/OspoClientServices/OspoLink.cs:
--------------------------------------------------------------------------------
1 | // Taken from https://github.com/dotnet/org-policy/tree/main/src/Microsoft.DotnetOrg.Ospo
2 |
3 | using System.Text.Json.Serialization;
4 |
5 | namespace Microsoft.DotnetOrg.Ospo;
6 |
7 | #pragma warning disable CS8618 // This is a serialized type.
8 | public sealed class OspoLink
9 | {
10 | [JsonPropertyName("github")]
11 | public GitHubInfo GitHubInfo { get; set; }
12 |
13 | [JsonPropertyName("aad")]
14 | public MicrosoftInfo MicrosoftInfo { get; set; }
15 | }
16 | #pragma warning restore CS8618
17 |
--------------------------------------------------------------------------------
/DotNet.DocsTools/OspoClientServices/OspoLinkSet.cs:
--------------------------------------------------------------------------------
1 | // Taken from https://github.com/dotnet/org-policy/tree/main/src/Microsoft.DotnetOrg.Ospo
2 |
3 | using System.Text.Json.Serialization;
4 |
5 | namespace Microsoft.DotnetOrg.Ospo;
6 |
7 | #pragma warning disable CS8618 // This is a serialized type.
8 | public sealed class OspoLinkSet
9 | {
10 | public OspoLinkSet()
11 | {
12 | }
13 |
14 | public void Initialize()
15 | {
16 | LinkByLogin = Links.ToDictionary(l => l.GitHubInfo.Login);
17 | }
18 |
19 | public IReadOnlyList Links { get; set; } = new List();
20 |
21 | [JsonIgnore]
22 | public IReadOnlyDictionary LinkByLogin { get; set; } = new Dictionary();
23 | }
24 | #pragma warning restore CS8618
25 |
26 |
--------------------------------------------------------------------------------
/DotNet.DocsTools/OspoClientServices/OspoUnauthorizedException.cs:
--------------------------------------------------------------------------------
1 | // Taken from https://github.com/dotnet/org-policy/tree/main/src/Microsoft.DotnetOrg.Ospo
2 |
3 | using System.Net;
4 |
5 | namespace Microsoft.DotnetOrg.Ospo;
6 |
7 | [Serializable]
8 | public class OspoUnauthorizedException : OspoException
9 | {
10 | public OspoUnauthorizedException()
11 | {
12 | }
13 |
14 | public OspoUnauthorizedException(string? message)
15 | : base(message)
16 | {
17 | }
18 |
19 | public OspoUnauthorizedException(string? message, Exception? inner)
20 | : base(message, inner)
21 | {
22 | }
23 |
24 | public OspoUnauthorizedException(string? message, HttpStatusCode code)
25 | : base(message, code)
26 | {
27 | }
28 | }
--------------------------------------------------------------------------------
/DotNet.DocsTools/Serialization/JsonSerializerOptionsDefaults.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 |
3 | namespace DotNetDocs.Tools.Serialization;
4 |
5 | internal static class JsonSerializerOptionsDefaults
6 | {
7 | ///
8 | internal static JsonSerializerOptions Shared { get; } =
9 | new(JsonSerializerDefaults.Web);
10 | }
11 |
--------------------------------------------------------------------------------
/DotnetDocsToolsTests/DotnetDocsTools.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | false
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | all
16 | runtime; build; native; contentfiles; analyzers; buildtransitive
17 |
18 |
19 | all
20 | runtime; build; native; contentfiles; analyzers; buildtransitive
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/DotnetDocsToolsTests/GraphQLProcessingTests/DefaultBranchTests.cs:
--------------------------------------------------------------------------------
1 | using DotNet.DocsTools.GitHubObjects;
2 | using System.Text.Json;
3 | using Xunit;
4 |
5 | namespace DotnetDocsTools.Tests.GraphQLProcessingTests;
6 |
7 | public class DefaultBranchTests
8 | {
9 | private const string ValidResult = """
10 | {
11 | "name": "main"
12 | }
13 | """;
14 |
15 |
16 | [Fact]
17 | public void DefaultBranchName_Is_Correct()
18 | {
19 | var variables = new DefaultBranchVariables
20 | {
21 | Organization = "dotnet",
22 | Repository = "docs"
23 | };
24 |
25 | JsonElement element = JsonDocument.Parse(ValidResult).RootElement;
26 | var issue = DefaultBranch.FromJsonElement(element, variables);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/GitHub.QuerySandbox/GitHub.QuerySandbox.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/GitHub.QuerySandbox/GlobalUsings.cs:
--------------------------------------------------------------------------------
1 | global using System.Text;
2 |
3 | global using GitHub.QuerySandbox.Spinners;
4 |
5 | global using Octokit;
6 | global using Octokit.Internal;
7 |
8 | global using Spectre.Console;
9 | global using SpectreEmoji = Spectre.Console.Emoji;
--------------------------------------------------------------------------------
/GitHub.QuerySandbox/Spinners/TimeTravelSpinner.cs:
--------------------------------------------------------------------------------
1 | namespace GitHub.QuerySandbox.Spinners;
2 |
3 | internal sealed class TimeTravelSpinner : Spinner
4 | {
5 | public override TimeSpan Interval => TimeSpan.FromMilliseconds(100);
6 | public override bool IsUnicode => true;
7 | public override IReadOnlyList Frames => new List
8 | {
9 | "🕚 ",
10 | "🕙 ",
11 | "🕘 ",
12 | "🕗 ",
13 | "🕖 ",
14 | "🕕 ",
15 | "🕔 ",
16 | "🕓 ",
17 | "🕒 ",
18 | "🕑 ",
19 | "🕐 ",
20 | "🕛 ",
21 | };
22 | }
23 |
--------------------------------------------------------------------------------
/GitHub.QuerySandbox/github-query-sandbox.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.7.33920.267
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GitHub.QuerySandbox", "GitHub.QuerySandbox.csproj", "{54D4AC77-C0F9-4FA5-A419-39D1B2D96652}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {54D4AC77-C0F9-4FA5-A419-39D1B2D96652}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {54D4AC77-C0F9-4FA5-A419-39D1B2D96652}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {54D4AC77-C0F9-4FA5-A419-39D1B2D96652}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {54D4AC77-C0F9-4FA5-A419-39D1B2D96652}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | GlobalSection(ExtensibilityGlobals) = postSolution
23 | SolutionGuid = {D79C8B19-C1D4-4069-9943-BFF249270EC1}
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/App.razor:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Not found
8 |
9 | Sorry, there's nothing at this address.
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/Components/ProgressIndicator.razor:
--------------------------------------------------------------------------------
1 |
7 |
8 | @code {
9 | [Parameter]
10 | public string Message { get; set; } = "🤓 Loading, please wait...";
11 | }
12 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/Extensions/LocalStorageServiceExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace GitHub.RepositoryExplorer.Client.Extensions;
2 |
3 | internal static class LocalStorageServiceExtensions
4 | {
5 | internal static T? TryGetItem(this ILocalStorageService localStorage, string key)
6 | {
7 | try
8 | {
9 | return localStorage.GetItem(key);
10 | }
11 | catch
12 | {
13 | return default;
14 | }
15 | }
16 |
17 | internal static void TrySetItem(this ILocalStorageService localStorage, string key, T value)
18 | {
19 | try
20 | {
21 | localStorage.SetItem(key, value);
22 | }
23 | catch { }
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/GlobalUsings.cs:
--------------------------------------------------------------------------------
1 | global using GitHub.RepositoryExplorer.Client;
2 | global using GitHub.RepositoryExplorer.Client.Components;
3 | global using GitHub.RepositoryExplorer.Client.Options;
4 | global using GitHub.RepositoryExplorer.Client.Services;
5 | global using GitHub.RepositoryExplorer.Models;
6 | global using Microsoft.AspNetCore.Components;
7 | global using Microsoft.AspNetCore.Components.Web;
8 | global using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
9 | global using Microsoft.Extensions.DependencyInjection;
10 | global using Microsoft.Extensions.Options;
11 | global using Microsoft.JSInterop;
12 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/HttpClientNames.cs:
--------------------------------------------------------------------------------
1 | namespace GitHub.RepositoryExplorer.Client;
2 |
3 | static class HttpClientNames
4 | {
5 | internal static string IssuesApi = nameof(IssuesApi);
6 | }
7 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/Models/IssueSummary.cs:
--------------------------------------------------------------------------------
1 | public record class IssueSummary
2 | {
3 | public bool IsLoading { get; init; } = true;
4 |
5 | public DateOnly Date { get; init; }
6 |
7 | public IEnumerable Data { get; init; } =
8 | Array.Empty();
9 | }
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/Models/RepoLabels.cs:
--------------------------------------------------------------------------------
1 | public record class RepoLabels
2 | {
3 | public bool IsLoading { get; init; } = true;
4 |
5 | public IssueClassificationModel IssueClassification { get; init; } = new();
6 | }
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/Models/Repository.cs:
--------------------------------------------------------------------------------
1 | public record class Repository(
2 | string? Org,
3 | string? Repo)
4 | {
5 | public bool IsAssigned => Org is { Length: > 0 } && Repo is { Length: > 0 };
6 | }
7 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/Options/IssuesApiOptions.cs:
--------------------------------------------------------------------------------
1 | namespace GitHub.RepositoryExplorer.Client.Options;
2 |
3 | public class IssuesApiOptions
4 | {
5 | public string ServerUrl { get; set; } = null!;
6 | }
7 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/Pages/Areas.razor.css:
--------------------------------------------------------------------------------
1 | .clickable-link {
2 | cursor: pointer;
3 | }
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/Pages/Index.razor:
--------------------------------------------------------------------------------
1 | @page "/"
2 |
3 | GitHub Issues | Home
4 |
5 |
6 |
7 | You're repo is configured as:
8 |
9 |
10 | @_config.FullyQualifiedOrgAndRepo
11 |
12 |
13 |
17 |
18 |
19 |
20 |
21 | @code {
22 | private ConfigureRepo _config = null!;
23 | }
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/Program.cs:
--------------------------------------------------------------------------------
1 | var builder = WebAssemblyHostBuilder.CreateDefault(args);
2 | builder.RootComponents.Add("#app");
3 | builder.RootComponents.Add("head::after");
4 |
5 | if (builder.HostEnvironment.IsDevelopment())
6 | {
7 | builder.Logging.SetMinimumLevel(LogLevel.Debug);
8 | }
9 |
10 | builder.Services.AddOptions();
11 | builder.Services.Configure(
12 | builder.Configuration.GetSection(nameof(IssuesApiOptions)));
13 |
14 | builder.Services.AddSingleton();
15 |
16 | builder.Services.AddHttpClient();
17 | builder.Services.AddHttpClient(
18 | HttpClientNames.IssuesApi,
19 | (services, client) =>
20 | {
21 | var options =
22 | services.GetRequiredService>().Value;
23 |
24 | client.BaseAddress = new Uri(options.ServerUrl);
25 | });
26 |
27 | builder.Services.AddSingleton();
28 | builder.Services.AddSingleton();
29 | builder.Services.AddSingleton();
30 | builder.Services.AddSingleton();
31 | builder.Services.AddSingleton();
32 | builder.Services.AddLocalStorageServices();
33 |
34 | await builder.Build().RunAsync();
35 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "iisSettings": {
3 | "windowsAuthentication": false,
4 | "anonymousAuthentication": true,
5 | "iisExpress": {
6 | "applicationUrl": "http://localhost:65506",
7 | "sslPort": 44398
8 | }
9 | },
10 | "profiles": {
11 | "GitHub.RepositoryExplorer.Client": {
12 | "commandName": "Project",
13 | "dotnetRunMessages": true,
14 | "launchBrowser": true,
15 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
16 | "applicationUrl": "https://localhost:7299;http://localhost:5299",
17 | "environmentVariables": {
18 | "ASPNETCORE_ENVIRONMENT": "Development"
19 | }
20 | },
21 | "IIS Express": {
22 | "commandName": "IISExpress",
23 | "launchBrowser": true,
24 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
25 | "environmentVariables": {
26 | "ASPNETCORE_ENVIRONMENT": "Development"
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/Services/AppInMemoryStateService.cs:
--------------------------------------------------------------------------------
1 | public sealed class AppInMemoryStateService
2 | {
3 | private Repository? _repoState;
4 | public Repository? RepoState
5 | {
6 | get => _repoState;
7 | set
8 | {
9 | _repoState = value;
10 | NotifyStateChanged();
11 | }
12 | }
13 |
14 |
15 | public event Action? OnChange;
16 |
17 | private void NotifyStateChanged() => OnChange?.Invoke();
18 | }
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/Services/IssuesClient.cs:
--------------------------------------------------------------------------------
1 | using System.Web;
2 |
3 | namespace GitHub.RepositoryExplorer.Client.Services;
4 |
5 | public sealed class IssuesClient
6 | {
7 | private readonly HttpClient _httpClient;
8 | private readonly Func _encode =
9 | static string (DateOnly date) => HttpUtility.UrlEncode($"{date:o}");
10 |
11 | public IssuesClient(IHttpClientFactory factory)
12 | {
13 | _httpClient = factory.CreateClient(HttpClientNames.IssuesApi);
14 | }
15 |
16 | public async Task GetIssuesForDateAsync(
17 | Repository state, DateOnly date, IssueClassificationModel model)
18 | {
19 | var (org, repo) = (state.Org, state.Repo);
20 | var route = _encode(date);
21 | try
22 | {
23 | var dailyRecord =
24 | await _httpClient.GetFromJsonAsync(
25 | $"api/issues/{org}/{repo}/{route}");
26 |
27 | return dailyRecord;
28 | }
29 | catch ( Exception ex )
30 | {
31 | Console.WriteLine(ex);
32 | return DailyRecordFactory.CreateMissingRecord(date, model, org, repo);
33 | }
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/Services/RespositoryLabelsClient.cs:
--------------------------------------------------------------------------------
1 | namespace GitHub.RepositoryExplorer.Client.Services;
2 |
3 | public class RepositoryLabelsClient
4 | {
5 | private readonly HttpClient _httpClient;
6 |
7 | public RepositoryLabelsClient(IHttpClientFactory factory)
8 | {
9 | _httpClient = factory.CreateClient(HttpClientNames.IssuesApi);
10 | }
11 |
12 | public async Task GetRepositoryLabelsAsync(Repository state)
13 | {
14 | var (org, repo) = (state.Org, state.Repo);
15 | var result =
16 | await _httpClient.GetFromJsonAsync(
17 | $"api/repositorylabels/{org}/{repo}");
18 |
19 | return result;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/Shared/MainLayout.razor:
--------------------------------------------------------------------------------
1 | @inherits LayoutComponentBase
2 |
3 |
4 |
7 |
8 |
9 |
12 |
13 |
14 |
15 | @Body
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/_Imports.razor:
--------------------------------------------------------------------------------
1 | @using System.Net.Http
2 | @using System.Net.Http.Json
3 | @using Microsoft.AspNetCore.Components.Forms
4 | @using Microsoft.AspNetCore.Components.Routing
5 | @using Microsoft.AspNetCore.Components.Web
6 | @using Microsoft.AspNetCore.Components.Web.Virtualization
7 | @using Microsoft.AspNetCore.Components.WebAssembly.Http
8 | @using Microsoft.JSInterop
9 | @using GitHub.RepositoryExplorer.Client
10 | @using GitHub.RepositoryExplorer.Client.Components
11 | @using GitHub.RepositoryExplorer.Client.Shared
12 | @using GitHub.RepositoryExplorer.Client.Pages
13 | @using ChartJs.Blazor
14 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/wwwroot/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "IssuesApiOptions": {
3 | "ServerUrl": "https://localhost:7039"
4 | }
5 | }
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/wwwroot/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "IssuesApiOptions": {
3 | "ServerUrl": "https://github-explorer-web-api.azurewebsites.net"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/wwwroot/css/open-iconic/ICON-LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Waybury
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet/docs-tools/e88a4c229f2fc2dbe5cfa3ffabbcef8489ffba50/GitHub.RepositoryExplorer.Client/wwwroot/css/open-iconic/font/fonts/open-iconic.eot
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet/docs-tools/e88a4c229f2fc2dbe5cfa3ffabbcef8489ffba50/GitHub.RepositoryExplorer.Client/wwwroot/css/open-iconic/font/fonts/open-iconic.otf
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet/docs-tools/e88a4c229f2fc2dbe5cfa3ffabbcef8489ffba50/GitHub.RepositoryExplorer.Client/wwwroot/css/open-iconic/font/fonts/open-iconic.ttf
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet/docs-tools/e88a4c229f2fc2dbe5cfa3ffabbcef8489ffba50/GitHub.RepositoryExplorer.Client/wwwroot/css/open-iconic/font/fonts/open-iconic.woff
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/wwwroot/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet/docs-tools/e88a4c229f2fc2dbe5cfa3ffabbcef8489ffba50/GitHub.RepositoryExplorer.Client/wwwroot/favicon.ico
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Client/wwwroot/icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet/docs-tools/e88a4c229f2fc2dbe5cfa3ffabbcef8489ffba50/GitHub.RepositoryExplorer.Client/wwwroot/icon-192.png
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Functions/Configuration/RepositoriesConfig.cs:
--------------------------------------------------------------------------------
1 | namespace GitHub.RepositoryExplorer.Functions.Configuration;
2 |
3 | public class RepositoriesConfig
4 | {
5 | public List Repositories { get; set; } = new();
6 | }
7 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Functions/Configuration/RepositoryConfig.cs:
--------------------------------------------------------------------------------
1 | namespace GitHub.RepositoryExplorer.Functions.Configuration;
2 |
3 | public class RepositoryConfig
4 | {
5 | public string? OrganizationName { get; set; }
6 | public string? RepositoryName { get; set; }
7 | }
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Functions/Properties/serviceDependencies.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "appInsights1": {
4 | "type": "appInsights"
5 | },
6 | "storage1": {
7 | "type": "storage",
8 | "connectionId": "AzureWebJobsStorage"
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Functions/Properties/serviceDependencies.local.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "appInsights1": {
4 | "type": "appInsights.sdk"
5 | },
6 | "storage1": {
7 | "type": "storage.emulator",
8 | "connectionId": "AzureWebJobsStorage"
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Functions/README.md:
--------------------------------------------------------------------------------
1 | # Functions App for GitHub.RepositoryExplorer
2 |
3 | Function app built using the Azure Function SDK v4 and .NET 6. This app contains timer triggered functions that will retrieve and store daily issue counts from the configured GitHub repositories.
4 |
5 | List of repositories configured in `appsettings.json`.
6 |
7 | Create a `local.settings.json` file with the following contents:
8 |
9 | {
10 | "IsEncrypted": false,
11 | "Values": {
12 | "AzureWebJobsStorage": "UseDevelopmentStorage=true",
13 | "FUNCTIONS_WORKER_RUNTIME": "dotnet",
14 | "GitHubKey": "YOUR GITHUB PERSONAL ACCESS TOKEN HERE",
15 | "RepositoryOptions__CosmosConnectionString": "YOUR COSMOS DB CONNECTION STRING HERE",
16 | "RepositoryOptions__DatabaseId": "IssueStatistics",
17 | "RepositoryOptions__ContainerId": "DailyStatistics"
18 | }
19 | }
20 |
21 | ## Running Function Manually
22 |
23 | When doing local development, to run a TimerTrigger function manually, send a POST request to the folllowing URL:
24 |
25 | `http://localhost:7071/admin/functions/{FunctionName}`
26 |
27 | with a JSON body:
28 |
29 | ```
30 | { "input": "test" }
31 | ```
32 |
33 | Example:
34 | `POST http://localhost:7071/admin/functions/CaptureDailyIssueCountsFunction`
35 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Functions/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 |
3 | }
4 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Functions/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "RepositoriesConfig": {
3 | "Repositories": [
4 | {
5 | "OrganizationName": "dotnet",
6 | "RepositoryName": "docs"
7 | }
8 | ]
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Functions/host.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0",
3 | "logging": {
4 | "applicationInsights": {
5 | "samplingSettings": {
6 | "isEnabled": true,
7 | "excludedTypes": "Request"
8 | }
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Models/GitHub.RepositoryExplorer.Models.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | Always
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Models/IssuesSnapshot.cs:
--------------------------------------------------------------------------------
1 | namespace GitHub.RepositoryExplorer.Models;
2 |
3 | ///
4 | /// A snapshot representation of issues.
5 | ///
6 | /// The product (ms.prod) value.
7 | /// The technology (ms.technology) value.
8 | /// The priority value, for example; Pri1.
9 | /// The product (ms.prod) value.
10 | /// The number of issues for a given snapshot.
11 | /// The date of the snapshot.
12 | /// The interval between snapshot counts, defaults to one day.
13 | public readonly record struct IssuesSnapshot(
14 | string? Product,
15 | string? Technology,
16 | string? Priority,
17 | string? Classification,
18 | int[] DailyCount,
19 | string StartDate,
20 | int Interval = 1)
21 | {
22 | public static implicit operator SnapshotKey(IssuesSnapshot snapshot) =>
23 | new (
24 | Product: snapshot.Product,
25 | Technology: snapshot.Technology,
26 | Priority: snapshot.Priority,
27 | Classification: snapshot.Classification);
28 |
29 | }
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Models/SnapshotKey.cs:
--------------------------------------------------------------------------------
1 | namespace GitHub.RepositoryExplorer.Models;
2 |
3 | public readonly record struct SnapshotKey(
4 | string? Product,
5 | string? Technology,
6 | string? Priority,
7 | string? Classification);
8 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.Services/GitHub.RepositoryExplorer.Services.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | 1.1.0.0
8 | 1.1.0.0
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.WebApi/CorsPolicy.cs:
--------------------------------------------------------------------------------
1 | namespace GitHub.RepositoryExplorer.WebApi;
2 |
3 | static class CorsPolicy
4 | {
5 | internal const string Name = nameof(Name);
6 | }
7 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.WebApi/GitHub.RepositoryExplorer.WebApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net9.0
4 | enable
5 | enable
6 | 7d02fdaa-bfe2-4c8f-aee9-77abea14057c
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.WebApi/GlobalUsings.cs:
--------------------------------------------------------------------------------
1 | global using GitHub.RepositoryExplorer.Models;
2 | global using GitHub.RepositoryExplorer.Services;
3 | global using GitHub.RepositoryExplorer.WebApi;
4 | global using Microsoft.AspNetCore.Cors;
5 | global using Microsoft.AspNetCore.Mvc;
6 | global using Microsoft.Azure.CosmosRepository;
7 | global using System.Net.Mime;
8 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.WebApi/Program.cs:
--------------------------------------------------------------------------------
1 | [assembly: ApiController]
2 |
3 | var builder = WebApplication.CreateBuilder(args);
4 |
5 | builder.Services.AddCors(
6 | options => options.AddPolicy(
7 | CorsPolicy.Name,
8 | policy => policy.WithOrigins("https://localhost:7299")
9 | .AllowAnyMethod()
10 | .AllowAnyHeader()
11 | .AllowCredentials()));
12 |
13 | builder.Services.AddMemoryCache();
14 | builder.Services.AddSingleton();
15 | builder.Services.AddResponseCaching();
16 | builder.Services.AddControllers();
17 | builder.Services.AddEndpointsApiExplorer();
18 | builder.Services.AddSwaggerGen();
19 | builder.Services.AddApplicationInsightsTelemetry();
20 | builder.Services.AddCosmosRepository();
21 |
22 | var app = builder.Build();
23 | if (app.Environment.IsDevelopment())
24 | {
25 | app.UseSwagger();
26 | app.UseSwaggerUI();
27 | }
28 |
29 | app.UseResponseCaching();
30 | app.UseHttpsRedirection();
31 | app.UseRouting();
32 | app.UseCors(CorsPolicy.Name);
33 | app.MapControllers();
34 | app.Run();
35 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.WebApi/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/launchsettings.json",
3 | "iisSettings": {
4 | "windowsAuthentication": false,
5 | "anonymousAuthentication": true,
6 | "iisExpress": {
7 | "applicationUrl": "http://localhost:53612",
8 | "sslPort": 44355
9 | }
10 | },
11 | "profiles": {
12 | "GitHub.RepositoryExplorer.WebApi": {
13 | "commandName": "Project",
14 | "dotnetRunMessages": true,
15 | "launchBrowser": true,
16 | "launchUrl": "swagger",
17 | "applicationUrl": "https://localhost:7039;http://localhost:5261",
18 | "environmentVariables": {
19 | "ASPNETCORE_ENVIRONMENT": "Development"
20 | }
21 | },
22 | "IIS Express": {
23 | "commandName": "IISExpress",
24 | "launchBrowser": true,
25 | "launchUrl": "swagger",
26 | "environmentVariables": {
27 | "ASPNETCORE_ENVIRONMENT": "Development"
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.WebApi/Properties/serviceDependencies.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "appInsights1": {
4 | "type": "appInsights"
5 | }
6 | }
7 | }
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.WebApi/Properties/serviceDependencies.local.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "appInsights1": {
4 | "type": "appInsights.sdk"
5 | }
6 | }
7 | }
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.WebApi/appsettings.Development.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/GitHub.RepositoryExplorer.WebApi/appsettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Logging": {
3 | "LogLevel": {
4 | "Default": "Information",
5 | "Microsoft.AspNetCore": "Warning"
6 | }
7 | },
8 | "AllowedHosts": "*",
9 | "RepositoryOptions" : {
10 | "CosmosConnectionString": "YOUR COSMOS DB CONNECTION STRING IN USER SECRETS",
11 | "DatabaseId": "IssueStatistics",
12 | "ContainerId": "DailyStatistics"
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/IssueCloser/BulkCloseConfig.cs:
--------------------------------------------------------------------------------
1 | namespace IssueCloser;
2 |
3 | ///
4 | /// The data object for close config records
5 | ///
6 | public record BulkCloseConfig(CloseCriteria Criteria, int AgeInMonths);
7 |
--------------------------------------------------------------------------------
/IssueCloser/CloseCriteria.cs:
--------------------------------------------------------------------------------
1 | namespace IssueCloser;
2 |
3 | ///
4 | /// The data record for matching values against close criteria.
5 | ///
6 | public record CloseCriteria(Priority PriLabel, bool HasDocIssue, bool IsInternal);
7 |
--------------------------------------------------------------------------------
/IssueCloser/IssueCloser.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 | 2.0.0.0
9 | 2.0.0.0
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | PreserveNewest
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/LICENSE-CODE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 | Copyright (c) Microsoft Corporation
3 |
4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
5 | associated documentation files (the "Software"), to deal in the Software without restriction,
6 | including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 | and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
8 | subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in all copies or substantial
11 | portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
14 | NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
15 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
16 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
17 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/PackageIndexer/CsvEntry.cs:
--------------------------------------------------------------------------------
1 | namespace PackageIndexer;
2 |
3 | public sealed class CsvEntry
4 | {
5 | public static CsvEntry Create(string packageNumber, string packageName, string packageVersion)
6 | {
7 | return new CsvEntry(packageNumber, packageName, packageVersion);
8 | }
9 |
10 | private CsvEntry(string packageNumber, string packageName, string packageVersion)
11 | {
12 | PackageNumber = packageNumber;
13 | PackageName = packageName;
14 | PackageVersion = packageVersion;
15 | }
16 |
17 | public string PackageNumber { get; set; }
18 | public string PackageName { get; set; }
19 | public string PackageVersion { get; set; }
20 | }
21 |
--------------------------------------------------------------------------------
/PackageIndexer/FindProjectsWithDocs.ps1:
--------------------------------------------------------------------------------
1 | Get-ChildItem -Path "C:\path\to\runtime\src\libraries" -Recurse -Filter "*.csproj" -File |
2 | Where-Object { $_.FullName -notlike "*\ref\*" -and $_.FullName -notlike "*\tests\*" -and $_.FullName -notlike "*\gen\*" -and $_.FullName -notlike "*\shims\*" -and $_.FullName -notlike "*\tools\*" -and $_.FullName -notlike "*\System.Private*\*" -and $_.FullName -notlike "*\Fuzzing\*" -and $_.FullName -notlike "*\externals.csproj" -and $_.FullName -notlike "*\Microsoft.NETCore.Platforms\*" -and $_.BaseName -notlike "System.Threading.RateLimiting" -and $_.BaseName -notlike "Microsoft.XmlSerializer.Generator" } |
3 | ForEach-Object {
4 | $content = Get-Content -Path $_.FullName -Raw
5 | if ($content -notmatch "UseCompilerGeneratedDocXmlFile") {
6 | $_.BaseName
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/PackageIndexer/NuGet/NuGetFeeds.cs:
--------------------------------------------------------------------------------
1 | namespace PackageIndexer;
2 |
3 | public static class NuGetFeeds
4 | {
5 | public static string NuGetOrg => "https://api.nuget.org/v3/index.json";
6 | public static string NightlyDotnet7 => "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json";
7 | public static string NightlyDotnet8 => "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet8/nuget/v3/index.json";
8 | public static string NightlyDotnet9 => "https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9/nuget/v3/index.json";
9 | public static string NightlyXamarin => "https://pkgs.dev.azure.com/azure-public/vside/_packaging/xamarin-impl/nuget/v3/index.json";
10 | public static string NightlyLatest => NightlyDotnet9;
11 | }
--------------------------------------------------------------------------------
/PackageIndexer/PackageEntry.cs:
--------------------------------------------------------------------------------
1 | namespace PackageIndexer;
2 |
3 | public sealed class PackageEntry
4 | {
5 | public static PackageEntry Create(string id, string version, string repo, IList frameworks)
6 | {
7 | return new PackageEntry(id, version, repo, frameworks);
8 | }
9 |
10 | private PackageEntry(string id, string version, string repo, IList frameworks)
11 | {
12 | Name = id;
13 | Version = version;
14 | Repository = repo;
15 | Frameworks = frameworks;
16 | }
17 |
18 | //public Guid Fingerprint { get; }
19 | public string Name { get; }
20 | public string Version { get; }
21 | public string Repository { get; }
22 | public IList Frameworks { get; }
23 |
24 | public void Write(Stream stream)
25 | {
26 | XmlEntryFormat.WritePackageEntry(stream, this);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/PackageIndexer/PackageIndexer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # .NET Docs: Tools and GitHub Actions
2 |
3 | [](https://github.com/dotnet/docs-tools/actions/workflows/codeql-analysis.yml) [](https://github.com/dotnet/docs-tools/actions/workflows/build-docs-verifier.yml) [](https://github.com/dotnet/docs-tools/actions/workflows/dotnet-build-validation.yml) [](https://github.com/dotnet/docs-tools/actions/workflows/node-build-validation.yml) [](https://github.com/dotnet/docs-tools/actions/workflows/quest.yml)
4 |
5 | This repo contains GitHub Actions and other tools that the .NET docs team uses to maintain quality. Many of the tools are designed to be invoked on DocFx repositories.
6 |
7 | For information about the code of conduct, see [Code of conduct](CODE-OF-CONDUCT.md).
8 |
--------------------------------------------------------------------------------
/RepoMan/Actions/CloseObject.cs:
--------------------------------------------------------------------------------
1 | namespace RepoMan.Actions;
2 |
3 | public sealed class CloseObject: IRunnerItem
4 | {
5 | public CloseObject()
6 | {
7 | }
8 |
9 | public async Task Run(State state)
10 | {
11 | await GithubCommand.Close(state);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/RepoMan/Actions/Comment.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using YamlDotNet.RepresentationModel;
3 |
4 | namespace RepoMan.Actions;
5 |
6 | public sealed class Comment : IRunnerItem
7 | {
8 | private readonly string _comment;
9 | private readonly string _value;
10 |
11 | public Comment(YamlNode node, State state)
12 | {
13 | _comment = node.ToString();
14 | }
15 |
16 | public async Task Run(State state)
17 | {
18 | state.Logger.LogInformation($"Adding comment");
19 | state.Logger.LogDebugger(_comment);
20 | await GithubCommand.AddComment(_comment, state);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/RepoMan/Actions/ProductTechLabels.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 |
3 | namespace RepoMan.Actions;
4 |
5 | public sealed class SetSvcSubSvcLabels: IRunnerItem
6 | {
7 | public SetSvcSubSvcLabels()
8 | {
9 | }
10 |
11 | public async Task Run(State state)
12 | {
13 | state.Logger.LogInformation($"Adding service and subservice labels");
14 |
15 | if (state.Variables.ContainsKey("ms.service"))
16 | state.Operations.LabelsAdd.Add($"{state.Variables["ms.service"]}/svc");
17 |
18 | if (state.Variables.ContainsKey("ms.subservice"))
19 | state.Operations.LabelsAdd.Add($"{state.Variables["ms.subservice"]}/subsvc");
20 |
21 | await Task.CompletedTask;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/RepoMan/Checks/CommentBody.cs:
--------------------------------------------------------------------------------
1 | using YamlDotNet.RepresentationModel;
2 |
3 | namespace RepoMan.Checks;
4 |
5 | public sealed class CommentBody : ICheck
6 | {
7 | public string RegEx { get; }
8 |
9 | public CommentBody(YamlMappingNode node, State state)
10 | {
11 | RegEx = node["value"].ToString();
12 | state.Logger.LogDebugger($"BUILD: comment-body {RegEx}");
13 | }
14 |
15 | public async Task Run(State state)
16 | {
17 | state.Logger.LogDebugger($"RUN: CommentBody regex check '{RegEx}'");
18 | if (Utilities.MatchRegex(RegEx, state.IssuePrBody ?? "", state))
19 | {
20 | state.Logger.LogDebugger($"RUN: CommentBody pass");
21 | return await Task.FromResult(true);
22 | }
23 |
24 | state.Logger.LogDebugger($"RUN: CommentBody fail");
25 | return await Task.FromResult(false);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/RepoMan/Checks/DocMetadata.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using YamlDotNet.RepresentationModel;
3 |
4 | namespace RepoMan.Checks;
5 |
6 | public sealed class DocMetadata : ICheck
7 | {
8 | public string Name { get; }
9 | public string Value { get; }
10 |
11 | public DocMetadata(YamlMappingNode node, State state)
12 | {
13 | state.Logger.LogDebugger($"BUILD: Check-metadata-comment");
14 |
15 | Name = node["name"].ToString();
16 | Value = node["value"].ToString();
17 |
18 | state.Logger.LogTrace($"BUILD: Name: {Name} Value: {Value}");
19 | }
20 |
21 | public async Task Run(State state)
22 | {
23 | bool result = false;
24 |
25 | state.Logger.LogInformation($"Evaluating comment metadata: {Name} for {Value}");
26 |
27 | if (state.DocIssueMetadata.ContainsKey(Name))
28 | result = Utilities.MatchRegex(Value, state.DocIssueMetadata[Name], state);
29 |
30 | if (result)
31 | state.Logger.LogInformation($"PASS");
32 | else
33 | state.Logger.LogInformation($"FAIL");
34 |
35 | return await Task.FromResult(result);
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/RepoMan/Checks/DocMetadataExists.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 |
3 | namespace RepoMan.Checks;
4 |
5 | public sealed class DocMetadataExists : ICheck
6 | {
7 | public DocMetadataExists(State state)
8 | {
9 | state.Logger.LogDebugger($"BUILD: Check-metadata-exists");
10 | }
11 |
12 | public async Task Run(State state)
13 | {
14 | state.Logger.LogInformation($"Evaluating if doc metadata exists");
15 |
16 | bool result = state.DocIssueMetadata.Count != 0;
17 |
18 | if (result)
19 | state.Logger.LogInformation($"PASS");
20 | else
21 | state.Logger.LogInformation($"FAIL");
22 |
23 | return await Task.FromResult(result);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/RepoMan/Checks/DocNewMetadataExists.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 |
3 | namespace RepoMan.Checks;
4 |
5 | public sealed class DocNewMetadataExists : ICheck
6 | {
7 | public DocNewMetadataExists(State state)
8 | {
9 | state.Logger.LogDebugger($"BUILD: Check-newmetadata-exists");
10 | }
11 |
12 | public async Task Run(State state)
13 | {
14 | state.Logger.LogInformation($"Evaluating if doc v2 metadata exists");
15 |
16 | if (state.IsV2Metadata)
17 | state.Logger.LogInformation($"PASS");
18 | else
19 | state.Logger.LogInformation($"FAIL");
20 |
21 | return await Task.FromResult(state.IsV2Metadata);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/RepoMan/Checks/ForceFail.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 |
3 | namespace RepoMan.Checks;
4 |
5 | public sealed class ForceFail : ICheck
6 | {
7 | public ForceFail()
8 | {
9 |
10 | }
11 |
12 | public async Task Run(State state)
13 | {
14 | state.Logger.LogInformation($"Check ForceFail");
15 |
16 | return await Task.FromResult(false);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/RepoMan/Checks/ICheck.cs:
--------------------------------------------------------------------------------
1 | namespace RepoMan.Checks;
2 |
3 | public interface ICheck
4 | {
5 | Task Run(State state);
6 | }
7 |
--------------------------------------------------------------------------------
/RepoMan/Checks/IsDraft.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using YamlDotNet.RepresentationModel;
3 |
4 | namespace RepoMan.Checks;
5 |
6 | public sealed class IsDraft : ICheck
7 | {
8 | public bool Condition { get; }
9 |
10 | public IsDraft(YamlMappingNode node, State state)
11 | {
12 | state.Logger.LogDebugger($"BUILD: IsDraft");
13 | Condition = Convert.ToBoolean(node["value"].ToString());
14 | state.Logger.LogTrace($"BUILD: - {Condition}");
15 | }
16 |
17 | public async Task Run(State state)
18 | {
19 | state.Logger.LogInformation($"Check IsDraft: {Condition}");
20 |
21 | if (!state.IsPullRequest)
22 | {
23 | state.Logger.LogError("Tried to check IsDraft on non-PR");
24 | return await Task.FromResult(false);
25 | }
26 |
27 | bool result = state.PullRequest?.Draft == Condition;
28 |
29 | if (result)
30 | state.Logger.LogInformation($"PASS");
31 | else
32 | state.Logger.LogInformation($"FAIL");
33 |
34 | return await Task.FromResult(result);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/RepoMan/Checks/Query.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using YamlDotNet.RepresentationModel;
3 |
4 | namespace RepoMan.Checks;
5 |
6 | public sealed class Query : ICheck
7 | {
8 | public string Value { get; }
9 |
10 | public Query(YamlMappingNode node, State state)
11 | {
12 | Value = node["value"].ToString();
13 | state.Logger.LogDebugger($"BUILD: Check-Query");
14 | state.Logger.LogTrace($"BUILD: {Value}");
15 | }
16 |
17 | public async Task Run(State state)
18 | {
19 | state.Logger.LogInformation($"Evaluating: {Value}");
20 |
21 | bool result = Utilities.TestStateJMES(Value, state);
22 |
23 | if (result)
24 | state.Logger.LogInformation($"PASS");
25 | else
26 | state.Logger.LogInformation($"FAIL");
27 |
28 | return await Task.FromResult(result);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/RepoMan/Checks/Variable.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 | using YamlDotNet.RepresentationModel;
3 |
4 | namespace RepoMan.Checks;
5 |
6 | public sealed class Variable : ICheck
7 | {
8 | public string Name { get; }
9 | public string Value { get; }
10 |
11 | public Variable(YamlMappingNode node, State state)
12 | {
13 | state.Logger.LogDebugger($"BUILD: Variable");
14 | Name = node["name"].ToString();
15 | Value = node["value"].ToString();
16 | state.Logger.LogTrace($"BUILD: - {Name}={Value}");
17 | }
18 |
19 | public async Task Run(State state)
20 | {
21 | state.Logger.LogInformation($"Check variable: {Name}={Value}");
22 |
23 | bool result = state.Variables.ContainsKey(Name) && state.Variables[Name] == Value;
24 |
25 | if (result)
26 | state.Logger.LogInformation($"PASS");
27 | else
28 | state.Logger.LogInformation($"FAIL");
29 |
30 | return await Task.FromResult(result);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/RepoMan/ILoggerExtensions.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Extensions.Logging;
2 |
3 | namespace RepoMan;
4 |
5 | public static class ILoggerExtensions
6 | {
7 | public static void LogDebugger(this ILogger logger, string msg, params object[] args)
8 | {
9 | if (Environment.GetEnvironmentVariable("logdebug", EnvironmentVariableTarget.Process) != null)
10 | logger.LogInformation(msg, args);
11 | else
12 | logger.LogDebug(msg, args);
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/RepoMan/IRunnerItem.cs:
--------------------------------------------------------------------------------
1 | namespace RepoMan;
2 |
3 | public interface IRunnerItem
4 | {
5 | Task Run(State state);
6 | }
7 |
--------------------------------------------------------------------------------
/RepoMan/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.Azure.Functions.Worker;
2 | using Microsoft.Extensions.DependencyInjection;
3 | using Microsoft.Extensions.Hosting;
4 |
5 | var host = new HostBuilder()
6 | .ConfigureFunctionsWebApplication()
7 | .ConfigureServices(services => {
8 | services.AddApplicationInsightsTelemetryWorkerService();
9 | services.ConfigureFunctionsApplicationInsights();
10 | })
11 | .Build();
12 |
13 | host.Run();
14 |
--------------------------------------------------------------------------------
/RepoMan/Properties/serviceDependencies.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "storage1": {
4 | "type": "storage",
5 | "connectionId": "AzureWebJobsStorage"
6 | },
7 | "appInsights1": {
8 | "type": "appInsights",
9 | "connectionId": "APPLICATIONINSIGHTS_CONNECTION_STRING",
10 | "dynamicId": null
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/RepoMan/Properties/serviceDependencies.local.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "appInsights1": {
4 | "type": "appInsights.sdk"
5 | },
6 | "storage1": {
7 | "type": "storage.emulator",
8 | "connectionId": "AzureWebJobsStorage"
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/RepoMan/Properties/serviceDependencies.repoman - Zip Deploy.json:
--------------------------------------------------------------------------------
1 | {
2 | "dependencies": {
3 | "appInsights1": {
4 | "secretStore": "AzureAppSettings",
5 | "resourceId": "/subscriptions/[parameters('subscriptionId')]/resourceGroups/[parameters('resourceGroupName')]/providers/microsoft.insights/components/repomanai",
6 | "type": "appInsights.azure",
7 | "connectionId": "APPLICATIONINSIGHTS_CONNECTION_STRING",
8 | "dynamicId": null
9 | }
10 | }
11 | }
--------------------------------------------------------------------------------
/RepoMan/RequestType.cs:
--------------------------------------------------------------------------------
1 | namespace RepoMan;
2 |
3 | public enum RequestType
4 | {
5 | PullRequest,
6 | Issue,
7 | Comment
8 | }
9 |
--------------------------------------------------------------------------------
/RepoMan/Types.cs:
--------------------------------------------------------------------------------
1 | namespace RepoMan;
2 |
3 | public enum RunnerItemTypes
4 | {
5 | Check,
6 | Label,
7 | Milestone,
8 | Project,
9 | Comment,
10 | Files,
11 | Issue,
12 | PullRquest,
13 | Variable,
14 | Assignee,
15 | Reviewer,
16 | Predefined,
17 | Close,
18 | Reopen,
19 | SvcSubSvcLabels
20 | }
21 |
22 | public enum RunnerItemSubTypes
23 | {
24 | Add,
25 | Remove,
26 | Set
27 | }
28 |
--------------------------------------------------------------------------------
/RepoMan/host.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0",
3 | "logging": {
4 | "applicationInsights": {
5 | "samplingSettings": {
6 | "isEnabled": true,
7 | "excludedTypes": "Request"
8 | },
9 | "enableLiveMetricsFilters": true
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/RepoMan/readme.md:
--------------------------------------------------------------------------------
1 | Source code for the github issue labeler used on https://github.com/dotnet/docs/
--------------------------------------------------------------------------------
/Sandbox/Program.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.DotnetOrg.Ospo;
2 |
3 | var azureAccessToken = Environment.GetEnvironmentVariable("AZURE_ACCESS_TOKEN");
4 |
5 | var client = new OspoClient(azureAccessToken!, true);
6 |
7 | var link = client != null ? await client.GetAsync("IEvangelist") : null;
8 |
9 | if (link is not null)
10 | {
11 | _ = link;
12 | }
13 |
--------------------------------------------------------------------------------
/Sandbox/Sandbox.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/SmallRepo/SmallRepo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/SmallRepo/action.yml:
--------------------------------------------------------------------------------
1 | name: Small test case
2 | description: Small Test case against the OSPO REST API
3 | author: 'Bill Wagner'
4 | branding:
5 | icon: refresh-cw
6 | color: purple
7 |
8 | runs:
9 | using: docker
10 | image: ../smalltest.Dockerfile
11 |
--------------------------------------------------------------------------------
/ThirdPartyNotices.md:
--------------------------------------------------------------------------------
1 | ## Legal Notices
2 | Microsoft and any contributors grant you a license to the Microsoft documentation and other content
3 | in this repository under the [Creative Commons Attribution 4.0 International Public License](https://creativecommons.org/licenses/by/4.0/legalcode),
4 | see the [LICENSE](LICENSE) file, and grant you a license to any code in the repository under the [MIT License](https://opensource.org/licenses/MIT), see the
5 | [LICENSE-CODE](LICENSE-CODE) file.
6 |
7 | Microsoft, Windows, Microsoft Azure and/or other Microsoft products and services referenced in the documentation
8 | may be either trademarks or registered trademarks of Microsoft in the United States and/or other countries.
9 | The licenses for this project do not grant you rights to use any Microsoft names, logos, or trademarks.
10 | Microsoft's general trademark guidelines can be found at http://go.microsoft.com/fwlink/?LinkID=254653.
11 |
12 | Privacy information can be found at https://privacy.microsoft.com/en-us/
13 |
14 | Microsoft and any contributors reserve all others rights, whether under their respective copyrights, patents,
15 | or trademarks, whether by implication, estoppel or otherwise.
--------------------------------------------------------------------------------
/WhatsNew.Cli/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": [
3 | "ms-dotnettools.csharp"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/WhatsNew.Cli/nuget/images/docs-logo-ms.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet/docs-tools/e88a4c229f2fc2dbe5cfa3ffabbcef8489ffba50/WhatsNew.Cli/nuget/images/docs-logo-ms.png
--------------------------------------------------------------------------------
/WhatsNew.Infrastructure.Tests/assets/MicrosoftDocs/azure-devops-docs-pr.json:
--------------------------------------------------------------------------------
1 | {
2 | "docSetProductName": "",
3 | "rootDirectory": "docs/",
4 | "docLinkSettings": {
5 | "linkFormat": "relative",
6 | "relativeLinkPrefix": "/azure/devops/"
7 | },
8 | "inclusionCriteria": {
9 | "minAdditionsToFile": 62
10 | },
11 | "areas": [
12 | {
13 | "names": [ "artifacts" ],
14 | "heading": "Artifacts"
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/WhatsNew.Infrastructure.Tests/assets/MicrosoftDocs/cpp-docs-pr.json:
--------------------------------------------------------------------------------
1 | {
2 | "docSetProductName": "C++, C, and Assembler",
3 | "rootDirectory": "docs/",
4 | "docLinkSettings": {
5 | "linkFormat": "relative",
6 | "relativeLinkPrefix": "/cpp/"
7 | },
8 | "inclusionCriteria": {
9 | "minAdditionsToFile": 10,
10 | "omitPullRequestTitles": true
11 | },
12 | "areas": []
13 | }
14 |
--------------------------------------------------------------------------------
/WhatsNew.Infrastructure.Tests/assets/dotnet/AspNetCore.Docs.json:
--------------------------------------------------------------------------------
1 | {
2 | "docSetProductName": "ASP.NET Core",
3 | "rootDirectory": "",
4 | "docLinkSettings": {
5 | "linkFormat": "xref"
6 | },
7 | "areas": [
8 | {
9 | "names": [ "azure" ],
10 | "heading": "Azure"
11 | }
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/WhatsNew.Infrastructure.Tests/assets/dotnet/docs.json:
--------------------------------------------------------------------------------
1 | {
2 | "docSetProductName": ".NET",
3 | "rootDirectory": "docs/",
4 | "docLinkSettings": {
5 | "linkFormat": "relative"
6 | },
7 | "inclusionCriteria": {
8 | },
9 | "areas": [
10 | {
11 | "names": [ "architecture" ],
12 | "heading": "Architecture guides"
13 | }
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/WhatsNew.Infrastructure.Tests/xunit.runner.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
3 | "methodDisplayOptions": "replaceUnderscoreWithSpace"
4 | }
5 |
--------------------------------------------------------------------------------
/WhatsNew.Infrastructure/Constants.cs:
--------------------------------------------------------------------------------
1 | namespace WhatsNew.Infrastructure;
2 |
3 | ///
4 | /// Constants used throughout the what's new solution's projects.
5 | ///
6 | public static class Constants
7 | {
8 | ///
9 | /// The directory name in the WhatsNew.Infrastructure project which stores the
10 | /// JSON configuration files for each docset.
11 | ///
12 | public const string ConfigurationDirectory = "Configuration";
13 |
14 | ///
15 | /// The name of the default directory to which the generated Markdown file is
16 | /// written.
17 | ///
18 | public const string MarkdownFileDirectoryName = "whatsnew";
19 |
20 | ///
21 | /// The suffix used to indicate a private GitHub repository.
22 | ///
23 | public const string PrivateRepoNameSuffix = "-pr";
24 | }
25 |
--------------------------------------------------------------------------------
/WhatsNew.Infrastructure/Models/DocLinkSettings.cs:
--------------------------------------------------------------------------------
1 | namespace WhatsNew.Infrastructure.Models;
2 |
3 | ///
4 | /// Encapsulates the settings that control the construction of doc
5 | /// links in the generated Markdown file.
6 | ///
7 | public class DocLinkSettings
8 | {
9 | ///
10 | /// The link format to use for links to docs appearing in the
11 | /// generated Markdown file.
12 | ///
13 | public LinkFormat LinkFormat { get; init; }
14 |
15 | ///
16 | /// The path that prefixes the doc link.
17 | ///
18 | ///
19 | /// This property is required when
20 | /// is .
21 | ///
22 | /// /dotnet/
23 | public string? RelativeLinkPrefix { get; init; }
24 | }
25 |
--------------------------------------------------------------------------------
/WhatsNew.Infrastructure/Models/NavigationDetails.cs:
--------------------------------------------------------------------------------
1 | namespace WhatsNew.Infrastructure.Models;
2 |
3 | ///
4 | /// This class defines the properties needed to update the TOC.YML and Index.YML files.
5 | ///
6 | ///
7 | /// These properties are used when you run the tool to create a PR for
8 | /// the what's new documents.
9 | ///
10 | public class NavigationDetails
11 | {
12 | ///
13 | /// Maximum number of articles live in the TOC.
14 | ///
15 | public int MaximumNumberOfArticles { get; set; }
16 |
17 | ///
18 | /// The name of the parent node in the TOC.
19 | ///
20 | public string TocParentNode { get; set; } = default!;
21 |
22 | ///
23 | /// Path from the root of the repository to the toc to modify
24 | ///
25 | public string RepoTocFolder { get; set; } = default!;
26 |
27 | ///
28 | /// The name of the parent node in the TOC.
29 | ///
30 | public string IndexParentNode { get; set; } = default!;
31 |
32 | ///
33 | /// Path from the root of the repository to the toc to modify
34 | ///
35 | public string RepoIndexFolder { get; set; } = default!;
36 | }
37 |
--------------------------------------------------------------------------------
/WhatsNew.Infrastructure/Models/RepositoryArea.cs:
--------------------------------------------------------------------------------
1 | namespace WhatsNew.Infrastructure.Models;
2 |
3 | ///
4 | /// Represents a name-value pair, where represents the
5 | /// directory name(s) within the repo and represents the
6 | /// heading text corresponding to that directory.
7 | ///
8 | public class RepositoryArea
9 | {
10 | ///
11 | /// A collection of directory names in the GitHub repository.
12 | ///
13 | public IEnumerable Names { get; init; } = null!;
14 |
15 | ///
16 | /// The heading text for the area/directory.
17 | ///
18 | public string Heading { get; init; } = null!;
19 | }
20 |
--------------------------------------------------------------------------------
/WhatsNew.Infrastructure/WhatsNew.Infrastructure.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | true
8 | 3.1.0.0
9 | 3.1.0.0
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/XmlDocConflictResolver/Docs/APIKind.cs:
--------------------------------------------------------------------------------
1 | internal enum APIKind
2 | {
3 | Type,
4 | Member
5 | }
6 |
--------------------------------------------------------------------------------
/XmlDocConflictResolver/Docs/DocsAssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 |
3 | internal class DocsAssemblyInfo
4 | {
5 | private readonly XElement _xEAssemblyInfo;
6 | public string AssemblyName => XmlHelper.GetChildElementValue(_xEAssemblyInfo, "AssemblyName");
7 |
8 | private List? _assemblyVersions;
9 | public List AssemblyVersions
10 | {
11 | get
12 | {
13 | if (_assemblyVersions == null)
14 | {
15 | _assemblyVersions = _xEAssemblyInfo.Elements("AssemblyVersion").Select(x => XmlHelper.GetNodesInPlainText(x)).ToList();
16 | }
17 | return _assemblyVersions;
18 | }
19 | }
20 |
21 | public DocsAssemblyInfo(XElement xeAssemblyInfo)
22 | {
23 | _xEAssemblyInfo = xeAssemblyInfo;
24 | }
25 |
26 | public override string ToString() => AssemblyName;
27 | }
--------------------------------------------------------------------------------
/XmlDocConflictResolver/Docs/DocsMemberSignature.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 |
3 | internal class DocsMemberSignature
4 | {
5 | private readonly XElement XEMemberSignature;
6 |
7 | public string Language => XmlHelper.GetAttributeValue(XEMemberSignature, "Language");
8 | public string Value => XmlHelper.GetAttributeValue(XEMemberSignature, "Value");
9 |
10 | public DocsMemberSignature(XElement xeMemberSignature)
11 | {
12 | XEMemberSignature = xeMemberSignature;
13 | }
14 | }
--------------------------------------------------------------------------------
/XmlDocConflictResolver/Docs/DocsParam.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 |
3 | internal class DocsParam
4 | {
5 | private readonly XElement _xEDocsParam;
6 |
7 | public IDocsAPI ParentAPI
8 | {
9 | get; private set;
10 | }
11 |
12 | public string Name => XmlHelper.GetAttributeValue(_xEDocsParam, "name");
13 | public string Value => XmlHelper.GetNodesInPlainText(_xEDocsParam);
14 |
15 | public DocsParam(IDocsAPI parentAPI, XElement xeDocsParam)
16 | {
17 | ParentAPI = parentAPI;
18 | _xEDocsParam = xeDocsParam;
19 | }
20 |
21 | public override string ToString() => Name;
22 | }
23 |
--------------------------------------------------------------------------------
/XmlDocConflictResolver/Docs/DocsRelated.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 |
3 | internal class DocsRelated
4 | {
5 | private readonly XElement _xERelatedArticle;
6 |
7 | public IDocsAPI ParentAPI
8 | {
9 | get; private set;
10 | }
11 |
12 | public string ArticleType => XmlHelper.GetAttributeValue(_xERelatedArticle, "type");
13 | public string Href => XmlHelper.GetAttributeValue(_xERelatedArticle, "href");
14 | public string Value => XmlHelper.GetNodesInPlainText(_xERelatedArticle);
15 |
16 | public DocsRelated(IDocsAPI parentAPI, XElement xeRelatedArticle)
17 | {
18 | ParentAPI = parentAPI;
19 | _xERelatedArticle = xeRelatedArticle;
20 | }
21 |
22 | public override string ToString() => Value;
23 | }
--------------------------------------------------------------------------------
/XmlDocConflictResolver/Docs/DocsTypeParam.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 |
3 | ///
4 | /// Each one of these typeparam objects live inside the Docs section inside the Member object.
5 | ///
6 | internal class DocsTypeParam
7 | {
8 | private readonly XElement _xEDocsTypeParam;
9 | public IDocsAPI ParentAPI
10 | {
11 | get; private set;
12 | }
13 |
14 | public string Name => XmlHelper.GetAttributeValue(_xEDocsTypeParam, "name");
15 |
16 | public string Value => XmlHelper.GetNodesInPlainText(_xEDocsTypeParam);
17 |
18 | public DocsTypeParam(IDocsAPI parentAPI, XElement xeDocsTypeParam)
19 | {
20 | ParentAPI = parentAPI;
21 | _xEDocsTypeParam = xeDocsTypeParam;
22 | }
23 | }
--------------------------------------------------------------------------------
/XmlDocConflictResolver/Docs/DocsTypeSignature.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 |
3 | internal class DocsTypeSignature
4 | {
5 | private readonly XElement _xETypeSignature;
6 |
7 | public string Language => XmlHelper.GetAttributeValue(_xETypeSignature, "Language");
8 | public string Value => XmlHelper.GetAttributeValue(_xETypeSignature, "Value");
9 |
10 | public DocsTypeSignature(XElement xeTypeSignature) => _xETypeSignature = xeTypeSignature;
11 | }
--------------------------------------------------------------------------------
/XmlDocConflictResolver/Docs/IDocsAPI.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 |
3 | internal interface IDocsAPI
4 | {
5 | public abstract APIKind Kind { get; }
6 | public abstract bool InheritDoc { get; }
7 | public abstract bool Changed { get; set; }
8 | public abstract string FilePath { get; set; }
9 | public abstract string DocId { get; }
10 | public abstract string DocIdUnprefixed { get; }
11 | public abstract string InheritDocCref { get; }
12 | public abstract XElement Docs { get; }
13 | public abstract List Params { get; }
14 | public abstract List TypeParams { get; }
15 | public abstract string Summary { get; }
16 | public abstract string Returns { get; }
17 | public abstract string Remarks { get; }
18 | }
--------------------------------------------------------------------------------
/XmlDocConflictResolver/IntelliSenseXml/IntelliSenseXmlException.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 |
3 | internal class IntelliSenseXmlException
4 | {
5 | public XElement XEException
6 | {
7 | get;
8 | private set;
9 | }
10 |
11 | private string _cref = string.Empty;
12 | public string Cref
13 | {
14 | get
15 | {
16 | if (string.IsNullOrWhiteSpace(_cref))
17 | {
18 | _cref = XmlHelper.GetAttributeValue(XEException, "cref");
19 | }
20 | return _cref;
21 | }
22 | }
23 |
24 | private string _value = string.Empty;
25 | public string Value
26 | {
27 | get
28 | {
29 | if (string.IsNullOrWhiteSpace(_value))
30 | {
31 | _value = XmlHelper.GetNodesInPlainText(XEException);
32 | }
33 | return _value;
34 | }
35 | set
36 | {
37 | _value = value;
38 |
39 | XEException.Value = value;
40 | }
41 | }
42 |
43 | public IntelliSenseXmlException(XElement xeException) => XEException = xeException;
44 |
45 | public override string ToString() => $"{Cref} - {Value}";
46 | }
47 |
--------------------------------------------------------------------------------
/XmlDocConflictResolver/IntelliSenseXml/IntelliSenseXmlFile.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using System.Xml.Linq;
3 |
4 | internal class IntelliSenseXmlFile
5 | {
6 | public IntelliSenseXmlFile(XDocument xDoc, string filePath, Encoding encoding)
7 | {
8 | Xdoc = xDoc;
9 | FilePath = filePath;
10 | FileEncoding = encoding;
11 | }
12 |
13 | public XDocument Xdoc { get; private set; }
14 | public string FilePath { get; private set; }
15 | public Encoding FileEncoding { get; private set; }
16 | public bool Changed { get; set; } = false;
17 | }
18 |
--------------------------------------------------------------------------------
/XmlDocConflictResolver/IntelliSenseXml/IntelliSenseXmlParam.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 |
3 | internal class IntelliSenseXmlParam
4 | {
5 | public XElement XEParam
6 | {
7 | get;
8 | private set;
9 | }
10 |
11 | private string _name = string.Empty;
12 | public string Name
13 | {
14 | get
15 | {
16 | if (string.IsNullOrWhiteSpace(_name))
17 | {
18 | _name = XmlHelper.GetAttributeValue(XEParam, "name");
19 | }
20 | return _name;
21 | }
22 | }
23 |
24 | private string _value = string.Empty;
25 | public string Value
26 | {
27 | get
28 | {
29 | if (string.IsNullOrWhiteSpace(_value))
30 | {
31 | _value = XmlHelper.GetNodesInPlainText(XEParam);
32 | }
33 | return _value;
34 | }
35 | set
36 | {
37 | _value = value;
38 |
39 | // Update the XML model too.
40 | XEParam.Value = _value;
41 | }
42 | }
43 |
44 | public IntelliSenseXmlParam(XElement xeParam) => XEParam = xeParam;
45 | }
46 |
--------------------------------------------------------------------------------
/XmlDocConflictResolver/IntelliSenseXml/IntelliSenseXmlTypeParam.cs:
--------------------------------------------------------------------------------
1 | using System.Xml.Linq;
2 |
3 | internal class IntelliSenseXmlTypeParam
4 | {
5 | public XElement XETypeParam;
6 |
7 | private string _name = string.Empty;
8 | public string Name
9 | {
10 | get
11 | {
12 | if (string.IsNullOrWhiteSpace(_name))
13 | {
14 | _name = XmlHelper.GetAttributeValue(XETypeParam, "name");
15 | }
16 | return _name;
17 | }
18 | }
19 |
20 | private string _value = string.Empty;
21 | public string Value
22 | {
23 | get
24 | {
25 | if (string.IsNullOrWhiteSpace(_value))
26 | {
27 | _value = XmlHelper.GetNodesInPlainText(XETypeParam);
28 | }
29 | return _value;
30 | }
31 | set
32 | {
33 | _value = value;
34 |
35 | XETypeParam.Value = value;
36 | }
37 | }
38 |
39 | public IntelliSenseXmlTypeParam(XElement xeTypeParam) => XETypeParam = xeTypeParam;
40 | }
--------------------------------------------------------------------------------
/XmlDocConflictResolver/Properties/launchSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "profiles": {
3 | "XmlDocConflictResolver": {
4 | "commandName": "Project",
5 | "commandLineArgs": "--ixml \"C:\\Users\\gewarren\\Desktop\\Test Files\\Logging.Console\" --ecmaxml C:\\Users\\gewarren\\dotnet-api-docs\\xml > output.txt"
6 | }
7 | }
8 | }
--------------------------------------------------------------------------------
/XmlDocConflictResolver/XmlDocConflictResolver.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/actions/dependabot-bot/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.dockerignore
3 | **/.env
4 | **/.git
5 | **/.gitignore
6 | **/.project
7 | **/.settings
8 | **/.toolstarget
9 | **/.vs
10 | **/.vscode
11 | **/*.*proj.user
12 | **/*.dbmdl
13 | **/*.jfm
14 | **/azds.yaml
15 | **/bin
16 | **/charts
17 | **/docker-compose*
18 | **/Dockerfile*
19 | **/node_modules
20 | **/npm-debug.log
21 | **/obj
22 | **/secrets.dev.yaml
23 | **/values.dev.yaml
24 | LICENSE
25 | README.md
--------------------------------------------------------------------------------
/actions/dependabot-bot/action.yml:
--------------------------------------------------------------------------------
1 | name: '.NET dependabot bot'
2 | description: Automatically keep dependabot.yml files updated.
3 | author: 'David Pine'
4 | branding:
5 | icon: shield
6 | color: blue
7 | inputs:
8 | root-directory:
9 | description: 'The root directory in which to run the automated dependabot evaluation.'
10 | default: '/github/workspace'
11 | dependabot-yml-path:
12 | description: 'The system file path to the dependabot.yml file.'
13 | default: '.github/dependabot.yml'
14 |
15 | runs:
16 | using: docker
17 | image: ./src/dependabot-bot/Dockerfile
18 | args:
19 | - ${{ inputs.root-directory }}
20 | - ${{ inputs.dependabot-yml-path }}
21 |
--------------------------------------------------------------------------------
/actions/dependabot-bot/src/dependabot-bot/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0 as build-env
2 | # Copy everything and publish the release (publish implicitly restores and builds)
3 | WORKDIR /app
4 | COPY . ./
5 | RUN dotnet publish "dependabot-bot.csproj" -c Release -o out --no-self-contained
6 |
7 | # Relayer the .NET SDK, anew with the build output
8 | FROM mcr.microsoft.com/dotnet/sdk:9.0
9 | COPY --from=build-env /app/out .
10 | ENTRYPOINT [ "dotnet", "/dependabot-bot.dll" ]
11 |
--------------------------------------------------------------------------------
/actions/dependabot-bot/src/dependabot-bot/Extensions/StringBuilderExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Dependabot.Bot.Extensions;
2 |
3 | internal static class StringBuilderExtensions
4 | {
5 | internal static void WriteLineToBufferAndOutput(
6 | this StringBuilder buffer, string content, bool isLimitReached)
7 | {
8 | if (isLimitReached)
9 | {
10 | WriteLine("LIMIT REACHED, OVERFLOW IS DISCARDED!");
11 | WriteLine(content);
12 | }
13 | else
14 | {
15 | buffer.AppendLine(content);
16 | WriteLine(content);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/actions/dependabot-bot/src/dependabot-bot/GlobalUsings.cs:
--------------------------------------------------------------------------------
1 | global using Dependabot.Bot.Extensions;
2 |
3 | global using System.Diagnostics.CodeAnalysis;
4 | global using System.Net.Http.Json;
5 | global using System.Text;
6 | global using System.Text.RegularExpressions;
7 |
8 | global using static System.Console;
--------------------------------------------------------------------------------
/actions/dependabot-bot/src/dependabot-bot/Program.Services.cs:
--------------------------------------------------------------------------------
1 | using Pathological.ProjectSystem.Services;
2 | using Microsoft.Extensions.DependencyInjection;
3 |
4 | static partial class Program
5 | {
6 | static IDiscoveryService AddAndGetDiscoveryService()
7 | {
8 | var serviceProvider = new ServiceCollection()
9 | .AddDotNetProjectSystem()
10 | .BuildServiceProvider();
11 |
12 | return serviceProvider.GetRequiredService();
13 | }
14 | }
--------------------------------------------------------------------------------
/actions/docs-verifier/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | insert_final_newline = true
6 |
7 | [*.{xml,csproj,props,targets}]
8 | indent_size = 2
9 |
10 | [*.cs]
11 | indent_size = 4
12 | tab_width = 4
13 | end_of_line = crlf
14 |
15 | dotnet_sort_system_directives_first = true
16 |
17 | # CA1801: Review unused parameters - already removed in NetAnalyzers 6 in favor of IDE0060
18 | dotnet_diagnostic.CA1801.severity = none
19 |
20 | # CA2007: Consider calling ConfigureAwait on the awaited task
21 | dotnet_diagnostic.CA2007.severity = none
22 |
23 | # IDE0044: Add readonly modifier
24 | dotnet_style_readonly_field = true
25 |
26 | # IDE0022: Use block body for methods
27 | dotnet_diagnostic.IDE0022.severity = silent
28 | csharp_style_expression_bodied_methods = when_on_single_line
29 |
30 | # IDE0021: Use block body for constructors
31 | dotnet_diagnostic.IDE0021.severity = silent
32 | csharp_style_expression_bodied_constructors = when_on_single_line
33 |
34 | # IDE0046: Convert to conditional expression
35 | dotnet_diagnostic.IDE0046.severity = silent
36 |
37 | # IDE0008: Use explicit type - Replaced with YAnalyzers.
38 | dotnet_diagnostic.IDE0008.severity = none
39 |
40 | # CA1014: Mark assemblies with CLSCompliant
41 | dotnet_diagnostic.CA1014.severity = none
42 |
--------------------------------------------------------------------------------
/actions/docs-verifier/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | enable
6 | true
7 | latest-All
8 | true
9 | true
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/actions/docs-verifier/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build
2 | WORKDIR /app
3 | COPY . ./
4 | RUN dotnet publish ./src/ActionRunner/ActionRunner.csproj -c Release -o out --no-self-contained
5 |
6 | # Build the runtime image
7 | FROM mcr.microsoft.com/dotnet/runtime:9.0
8 | COPY --from=build /app/out .
9 |
10 | ENTRYPOINT [ "dotnet", "/ActionRunner.dll" ]
11 |
--------------------------------------------------------------------------------
/actions/docs-verifier/README.md:
--------------------------------------------------------------------------------
1 | # MSDocs Build Verifier
2 |
3 | A work-in-progress for a GitHub Action that does various checks for MS Docs repositories. This is based on [markdown-links-verifier](https://github.com/Youssef1313/markdown-links-verifier).
4 |
--------------------------------------------------------------------------------
/actions/docs-verifier/action.yml:
--------------------------------------------------------------------------------
1 | name: MSDocs Build Verifier
2 | description: Various checks for MSDocs repositories
3 |
4 | runs:
5 | using: docker
6 | image: Dockerfile
7 |
--------------------------------------------------------------------------------
/actions/docs-verifier/docs/json-config-file.md:
--------------------------------------------------------------------------------
1 | # Configuration file
2 |
3 | Starting with v0.0.8, a configuration file *markdown-links-verifier-config.json* support was added.
4 |
5 | ## `excludeStartingWith`
6 |
7 | Starting with v0.0.8, the configuration file can contain an `excludeStartingWith` array used to exclude links starting with given prefixes.
8 |
9 | ### Example
10 |
11 | Given the following *markdown-links-verifier-config.json* file in the repository root, it will disallow links starting with `xref:` or `~/` from being verified:
12 |
13 | ```json
14 | {
15 | "excludeStartingWith": [
16 | "xref:",
17 | "~/",
18 | ]
19 | }
20 | ```
21 |
22 | ### Rationale (use case)
23 |
24 | Some repositories may be using specific markdown extensions that shouldn't be flagged. For example, Microsoft Docs has "xref:" for API links. The workflow shouldn't attempt to analyze them.
25 |
26 | See [issue #63](https://github.com/Youssef1313/markdown-links-verifier/issues/63) for more information.
--------------------------------------------------------------------------------
/actions/docs-verifier/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/ActionRunner/ActionRunner.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/BuildVerifier.IO.Abstractions/BaseMappedConfigurationReader.cs:
--------------------------------------------------------------------------------
1 | namespace BuildVerifier.IO.Abstractions;
2 |
3 | public abstract class BaseMappedConfigurationReader
4 | : BaseConfigurationReader
5 | where TConfigurationFile : class
6 | {
7 | ///
8 | /// Maps the into a consumer-defined .
9 | ///
10 | public abstract ValueTask MapConfigurationAsync();
11 | }
12 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/BuildVerifier.IO.Abstractions/BuildVerifier.IO.Abstractions.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/GitHub/GitHub.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/GitHub/PullRequestFileExtensions.cs:
--------------------------------------------------------------------------------
1 | using Octokit;
2 |
3 | namespace GitHub;
4 |
5 | public static class PullRequestFileExtensions
6 | {
7 | // Didn't find documentation for these values :(
8 | private const string FILE_ADDED_STATUS = "added";
9 | private const string FILE_RENAMED_STATUS = "renamed";
10 | private const string FILE_REMOVED_STATUS = "removed";
11 |
12 | ///
13 | /// An added file has a non-null and
14 | ///
15 | public static bool IsRenamed(this PullRequestFile file) => file?.Status == FILE_RENAMED_STATUS;
16 |
17 | ///
18 | /// An added file has a null
19 | ///
20 | public static bool IsAdded(this PullRequestFile file) => file?.Status == FILE_ADDED_STATUS;
21 |
22 | ///
23 | /// An added file has a null
24 | ///
25 | public static bool IsRemoved(this PullRequestFile file) => file?.Status == FILE_REMOVED_STATUS;
26 | }
27 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/MarkdownLinksVerifier/Configuration/ConfigurationReader.cs:
--------------------------------------------------------------------------------
1 | using BuildVerifier.IO.Abstractions;
2 |
3 | namespace MarkdownLinksVerifier.Configuration;
4 |
5 | public class ConfigurationReader : BaseConfigurationReader
6 | {
7 | public ConfigurationReader()
8 | {
9 | ConfigurationFileName = "markdown-links-verifier-config.json";
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/MarkdownLinksVerifier/Configuration/MarkdownLinksVerifierConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Immutable;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace MarkdownLinksVerifier.Configuration;
5 |
6 | public record MarkdownLinksVerifierConfiguration(
7 | [property: JsonPropertyName("excludeStartingWith")] ImmutableArray ExcludeStartingWith)
8 | {
9 | public bool IsLinkExcluded(string link)
10 | => !ExcludeStartingWith.IsDefaultOrEmpty
11 | && ExcludeStartingWith.Any(excludedPrefix => link.StartsWith(excludedPrefix, StringComparison.Ordinal));
12 | }
13 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/MarkdownLinksVerifier/LinkClassifier/Classifier.cs:
--------------------------------------------------------------------------------
1 | namespace MarkdownLinksVerifier.LinkClassifier;
2 |
3 | internal static class Classifier
4 | {
5 | internal static LinkClassification Classify(string link)
6 | {
7 | if (Uri.TryCreate(link, UriKind.Absolute, out Uri? uri))
8 | {
9 | return uri.Scheme switch
10 | {
11 | "http" => LinkClassification.Online,
12 | "https" => LinkClassification.Online,
13 | "ftp" => LinkClassification.Online,
14 | "mailto" => LinkClassification.Mailto,
15 | _ => LinkClassification.Local
16 | };
17 | }
18 |
19 | return LinkClassification.Local;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/MarkdownLinksVerifier/LinkClassifier/LinkClassification.cs:
--------------------------------------------------------------------------------
1 | namespace MarkdownLinksVerifier.LinkClassifier;
2 |
3 | internal enum LinkClassification
4 | {
5 | ///
6 | /// Indicates an http/https link.
7 | ///
8 | Online,
9 | ///
10 | /// Indicates a link to a local file.
11 | ///
12 | Local,
13 | ///
14 | /// Indicates a mailto:
link.
15 | ///
16 | Mailto,
17 | }
18 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/MarkdownLinksVerifier/LinkValidator/ILinkValidator.cs:
--------------------------------------------------------------------------------
1 | namespace MarkdownLinksVerifier.LinkValidator;
2 |
3 | internal interface ILinkValidator
4 | {
5 | ValidationResult Validate(string link, string filePath);
6 | }
7 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/MarkdownLinksVerifier/LinkValidator/MailtoLinkValidator.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 | using System.Diagnostics;
3 |
4 | namespace MarkdownLinksVerifier.LinkValidator;
5 |
6 | internal class MailtoLinkValidator : ILinkValidator
7 | {
8 | private static readonly EmailAddressAttribute emailAddressAttribute = new();
9 |
10 | public ValidationResult Validate(string link, string filePath)
11 | {
12 | Debug.Assert(link.StartsWith("mailto:", StringComparison.OrdinalIgnoreCase));
13 | return new ValidationResult { AbsolutePathWithoutHeading = link, State = emailAddressAttribute.IsValid(link["mailto:".Length..]) ? ValidationState.Valid : ValidationState.LinkNotFound };
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/MarkdownLinksVerifier/LinkValidator/OnlineLinkValidator.cs:
--------------------------------------------------------------------------------
1 | namespace MarkdownLinksVerifier.LinkValidator;
2 |
3 | // Singleton?
4 | internal class OnlineLinkValidator : ILinkValidator
5 | {
6 | public ValidationResult Validate(string link, string filePath)
7 | {
8 | // TODO: implement this.
9 | return new ValidationResult { State = ValidationState.Valid, AbsolutePathWithoutHeading = link };
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/MarkdownLinksVerifier/LinkValidator/ValidationResult.cs:
--------------------------------------------------------------------------------
1 | namespace MarkdownLinksVerifier;
2 |
3 | ///
4 | /// For a link on the form [Text](./path/to/file.md#heading-reference):
5 | ///
6 | /// - If file.md is found and the heading reference is correct, result will be
7 | /// - If file.md is found but the heading reference is invalid, result will be
8 | /// - If file.md is not found, result will be
9 | ///
10 | ///
11 | internal enum ValidationState
12 | {
13 | Valid,
14 | LinkNotFound,
15 | HeadingNotFound,
16 | }
17 |
18 | internal struct ValidationResult
19 | {
20 | public ValidationState State;
21 |
22 | ///
23 | /// The expected absolute path of the linked file.
24 | ///
25 | public string AbsolutePathWithoutHeading;
26 | }
27 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/MarkdownLinksVerifier/MarkdownLinksVerifier.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/RedirectionVerifier/DocfxConfigurationReader.cs:
--------------------------------------------------------------------------------
1 | using BuildVerifier.IO.Abstractions;
2 | using Microsoft.Extensions.FileSystemGlobbing;
3 |
4 | namespace RedirectionVerifier;
5 |
6 | public class DocfxConfigurationReader
7 | : BaseMappedConfigurationReader>
8 | {
9 | private static readonly Matcher s_matchAllMatcher = new Matcher().AddInclude("**");
10 |
11 | public DocfxConfigurationReader()
12 | {
13 | ConfigurationFileName = "docfx.json";
14 | }
15 |
16 | public override async ValueTask> MapConfigurationAsync()
17 | {
18 | DocfxConfiguration? configuration = await ReadConfigurationAsync();
19 | return AdjustMatchers(configuration?.GetMatchers());
20 | }
21 |
22 | private static IEnumerable AdjustMatchers(IEnumerable? matchers)
23 | => (matchers is null || !matchers.Any())
24 | ? new[] { s_matchAllMatcher }
25 | : matchers;
26 | }
27 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/RedirectionVerifier/NavigationOptions.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace RedirectionVerifier;
4 |
5 | public record NavigationOptions(
6 | [property: JsonPropertyName("repoTocFolder")] string? RepoTocFolder,
7 | [property: JsonPropertyName("repoIndexFolder")] string? RepoIndexFolder)
8 | {
9 | ///
10 | /// The configured path for the "What's new" content.
11 | ///
12 | internal string? WhatsNewPath => RepoTocFolder ?? RepoIndexFolder;
13 | }
14 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/RedirectionVerifier/OpenPublishingConfig.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Immutable;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace RedirectionVerifier;
5 |
6 | public sealed class OpenPublishingConfig
7 | {
8 | [JsonPropertyName("redirection_files")]
9 | public ImmutableArray? RedirectionFiles { get; set; } = null;
10 | }
11 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/RedirectionVerifier/OpenPublishingConfigReader.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Immutable;
2 | using BuildVerifier.IO.Abstractions;
3 |
4 | namespace RedirectionVerifier;
5 |
6 | public class OpenPublishingConfigReader
7 | : BaseMappedConfigurationReader?>
8 | {
9 | public OpenPublishingConfigReader()
10 | {
11 | ConfigurationFileName = ".openpublishing.publish.config.json";
12 | }
13 |
14 | public override async ValueTask?> MapConfigurationAsync()
15 | {
16 | OpenPublishingConfig? configuration = await ReadConfigurationAsync();
17 | if (configuration is { RedirectionFiles: { Length: > 0 } })
18 | {
19 | return configuration.RedirectionFiles;
20 | }
21 |
22 | return default;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/RedirectionVerifier/OpenPublishingRedirectionReader.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Immutable;
2 | using BuildVerifier.IO.Abstractions;
3 |
4 | namespace RedirectionVerifier;
5 |
6 | public class OpenPublishingRedirectionReader
7 | : BaseMappedConfigurationReader>
8 | {
9 | public OpenPublishingRedirectionReader(string configFileName)
10 | {
11 | ConfigurationFileName = configFileName;
12 | }
13 |
14 | public override async ValueTask> MapConfigurationAsync()
15 | {
16 | OpenPublishingRedirections? configuration = await ReadConfigurationAsync();
17 | if (configuration is { Redirections: { Length: > 0 } })
18 | {
19 | return configuration.Redirections;
20 | }
21 |
22 | return default;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/RedirectionVerifier/OpenPublishingRedirections.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Immutable;
2 | using System.Text.Json.Serialization;
3 |
4 | namespace RedirectionVerifier;
5 |
6 | public sealed class OpenPublishingRedirections
7 | {
8 | [JsonPropertyName("redirections")]
9 | public ImmutableArray Redirections { get; set; }
10 | }
11 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/RedirectionVerifier/Redirection.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace RedirectionVerifier;
4 |
5 | public sealed class Redirection
6 | {
7 | [JsonPropertyName("source_path")]
8 | public string? SourcePath { get; set; } = null;
9 |
10 | [JsonPropertyName("source_path_from_root")]
11 | public string? SourcePathFromRoot { get; set; } = null;
12 |
13 | [JsonPropertyName("redirect_url")]
14 | #pragma warning disable CA1056 // URI-like properties should not be strings → Could throw
15 | public string RedirectUrl { get; set; } = null!;
16 | #pragma warning restore CA1056 // URI-like properties should not be strings
17 |
18 | public bool MatchesSourcePath(string path)
19 | => SourcePath == path || SourcePathFromRoot == $"/{path}";
20 | }
21 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/RedirectionVerifier/RedirectionHelpers.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Immutable;
2 |
3 | namespace RedirectionVerifier;
4 |
5 | public static class RedirectionHelpers
6 | {
7 | public static async Task?> GetRedirectionFilesAsync()
8 | {
9 | OpenPublishingConfigReader configReader = new();
10 | return await configReader.MapConfigurationAsync();
11 | }
12 |
13 | public static async Task> GetRedirectionFileNames()
14 | {
15 | ImmutableArray? redirectionFileNames = await GetRedirectionFilesAsync();
16 |
17 | // If no redirection files are found in the OPS config, just use the default name.
18 | if (redirectionFileNames == null)
19 | redirectionFileNames = ImmutableArray.Create(".openpublishing.redirection.json");
20 |
21 | Console.WriteLine($"The following {redirectionFileNames.Value.Length} redirection files are registered:");
22 | foreach (string filename in redirectionFileNames)
23 | {
24 | Console.WriteLine(filename);
25 | }
26 |
27 | return redirectionFileNames.Value;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/RedirectionVerifier/RedirectionVerifier.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/RedirectionVerifier/WhatsNewConfiguration.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json.Serialization;
2 |
3 | namespace RedirectionVerifier;
4 |
5 | ///
6 | /// Schema: https://whatsnewapi.azurewebsites.net/schema
7 | /// Omitted parts of this that are not relevant to our needs.
8 | ///
9 | public record WhatsNewConfiguration(
10 | [property: JsonPropertyName("docSetProductName")] string DocSetProductName,
11 | [property: JsonPropertyName("navigationOptions")] NavigationOptions? NavigationOptions);
12 |
--------------------------------------------------------------------------------
/actions/docs-verifier/src/RedirectionVerifier/WhatsNewConfigurationReader.cs:
--------------------------------------------------------------------------------
1 | using BuildVerifier.IO.Abstractions;
2 |
3 | namespace RedirectionVerifier;
4 |
5 | public class WhatsNewConfigurationReader
6 | : BaseMappedConfigurationReader
7 | {
8 | public WhatsNewConfigurationReader()
9 | {
10 | ConfigurationFileName = ".whatsnew.json";
11 | }
12 |
13 | public override async ValueTask MapConfigurationAsync()
14 | {
15 | WhatsNewConfiguration? configuration = await ReadConfigurationAsync();
16 | if (configuration?.NavigationOptions is not null)
17 | {
18 | return configuration.NavigationOptions.WhatsNewPath;
19 | }
20 |
21 | return default;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/actions/docs-verifier/tests/GitHub.UnitTests/GitHub.UnitTests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 |
8 | false
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | runtime; build; native; contentfiles; analyzers; buildtransitive
17 | all
18 |
19 |
20 | runtime; build; native; contentfiles; analyzers; buildtransitive
21 | all
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/actions/docs-verifier/tests/MarkdownLinksVerifier/GlobalSuppressions.cs:
--------------------------------------------------------------------------------
1 | // This file is used by Code Analysis to maintain SuppressMessage
2 | // attributes that are applied to this project.
3 | // Project-level suppressions either have no target or are given
4 | // a specific target and scoped to a namespace, type, member, etc.
5 |
6 | using System.Diagnostics.CodeAnalysis;
7 |
8 | [assembly: SuppressMessage("Naming", "CA1707:Identifiers should not contain underscores", Justification = "Underscores are okay for unit tests")]
9 | [assembly: SuppressMessage("Style", "IDE0022:Use expression body for methods", Justification = "Noisy for test code")]
10 |
--------------------------------------------------------------------------------
/actions/docs-verifier/tests/MarkdownLinksVerifier/LinkValidatorTests/MailtoLinkValidatorTests.cs:
--------------------------------------------------------------------------------
1 | using MarkdownLinksVerifier.LinkValidator;
2 | using Xunit;
3 |
4 | namespace MarkdownLinksVerifier.UnitTests.LinkValidatorTests;
5 |
6 | public class MailtoLinkValidatorTests
7 | {
8 | [Fact]
9 | public void TestEmptyMailto()
10 | {
11 | Assert.Equal(ValidationState.LinkNotFound, new MailtoLinkValidator().Validate("mailto:", "UNUSED").State);
12 | }
13 |
14 | [Fact]
15 | public void TestInvalidEmail()
16 | {
17 | Assert.Equal(ValidationState.LinkNotFound, new MailtoLinkValidator().Validate("mailto:person", "UNUSED").State);
18 | }
19 |
20 | [Fact]
21 | public void TestValidEmail()
22 | {
23 | Assert.Equal(ValidationState.Valid, new MailtoLinkValidator().Validate("mailto:person@company.com", "UNUSED").State);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/actions/docs-verifier/tests/MarkdownLinksVerifier/LinkValidatorTests/Utilities/FilesCollection.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 |
3 | namespace MarkdownLinksVerifier.UnitTests.LinkValidatorTests;
4 |
5 | internal sealed class FilesCollection : IEnumerable>
6 | {
7 | private readonly Dictionary _files = new();
8 |
9 | public void Add(string path, string contents)
10 | => _files.Add(path.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar), contents);
11 |
12 | public IEnumerator> GetEnumerator() => _files.GetEnumerator();
13 |
14 | IEnumerator IEnumerable.GetEnumerator() => _files.GetEnumerator();
15 | }
16 |
--------------------------------------------------------------------------------
/actions/docs-verifier/tests/MarkdownLinksVerifier/MarkdownLinksVerifier.UnitTests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | false
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | runtime; build; native; contentfiles; analyzers; buildtransitive
16 | all
17 |
18 |
19 | runtime; build; native; contentfiles; analyzers; buildtransitive
20 | all
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/actions/docs-verifier/valid-test-cases/MSDocsSpecific/Includes/aspnetcore.md:
--------------------------------------------------------------------------------
1 | The following breaking changes in ASP.NET Core 3.0 and 3.1 are documented on this page:
2 | - [Obsolete Antiforgery, CORS, Diagnostics, MVC, and Routing APIs removed](#obsolete-antiforgery-cors-diagnostics-mvc-and-routing-apis-removed)
3 |
4 |
5 | [!INCLUDE[Obsolete Antiforgery, CORS, Diagnostics, MVC, and Routing APIs removed](~/actions/docs-verifier/valid-test-cases/MSDocsSpecific/Includes/include.md)]
6 |
--------------------------------------------------------------------------------
/actions/docs-verifier/valid-test-cases/MSDocsSpecific/Includes/include.md:
--------------------------------------------------------------------------------
1 | ### Obsolete Antiforgery, CORS, Diagnostics, MVC, and Routing APIs removed
2 |
3 | Obsolete members and compatibility switches in ASP.NET Core 2.2 were removed.
4 |
--------------------------------------------------------------------------------
/actions/docs-verifier/valid-test-cases/MSDocsSpecific/Includes2/core/compatibility/2.1.md:
--------------------------------------------------------------------------------
1 | ## MSBuild
2 | - [Project tools now included in SDK](#project-tools-now-included-in-sdk)
3 | [!INCLUDE [DotNetCliToolReference project elements removed for bundled tools](../../includes/dotnetclitoolreference.md)]
4 |
--------------------------------------------------------------------------------
/actions/docs-verifier/valid-test-cases/MSDocsSpecific/Includes2/core/tools/sdk-errors/netsdk1059.md:
--------------------------------------------------------------------------------
1 | For more information, see [Project tools now included in SDK](../../compatibility/2.1.md#project-tools-now-included-in-sdk).
--------------------------------------------------------------------------------
/actions/docs-verifier/valid-test-cases/MSDocsSpecific/Includes2/includes/dotnetclitoolreference.md:
--------------------------------------------------------------------------------
1 | ### Project tools now included in SDK
2 |
3 | The .NET Core 2.1 SDK now includes common CLI tooling, and you no longer need to reference these tools from the project.
4 |
--------------------------------------------------------------------------------
/actions/docs-verifier/valid-test-cases/MarkdownLinksVerifier/test-query-parameters/File.md:
--------------------------------------------------------------------------------
1 | 
2 | [text](image.png)
3 | 
4 | [text](image.png?raw=true)
5 |
6 | 
7 | [text](./image.png)
8 | 
9 | [text](./image.png?raw=true)
10 |
--------------------------------------------------------------------------------
/actions/docs-verifier/valid-test-cases/MarkdownLinksVerifier/test-query-parameters/image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet/docs-tools/e88a4c229f2fc2dbe5cfa3ffabbcef8489ffba50/actions/docs-verifier/valid-test-cases/MarkdownLinksVerifier/test-query-parameters/image.png
--------------------------------------------------------------------------------
/actions/docs-verifier/valid-test-cases/MarkdownLinksVerifier/test1/File1.md:
--------------------------------------------------------------------------------
1 | [text](File1.md)
2 | [text](./File1.md)
3 | [text](/actions/docs-verifier/valid-test-cases/MarkdownLinksVerifier/test1/File1.md)
4 | [text](folder/Name%20With%20Space.md)
5 | [text](folder)
6 | [text](./folder)
7 | [text]()
8 |
--------------------------------------------------------------------------------
/actions/docs-verifier/valid-test-cases/MarkdownLinksVerifier/test1/folder/Name With Space.md:
--------------------------------------------------------------------------------
1 | [text](../File1.md)
2 | [text](.././File1.md)
3 |
--------------------------------------------------------------------------------
/actions/docs-verifier/valid-test-cases/README.md:
--------------------------------------------------------------------------------
1 | # Test cases
2 |
3 | This folder holds actual test cases that the tool will run *directly* against through the dogfooding workflow.
4 |
--------------------------------------------------------------------------------
/actions/sequester/.dockerignore:
--------------------------------------------------------------------------------
1 | **/.classpath
2 | **/.dockerignore
3 | **/.env
4 | **/.git
5 | **/.gitignore
6 | **/.project
7 | **/.settings
8 | **/.toolstarget
9 | **/.vs
10 | **/.vscode
11 | **/*.*proj.user
12 | **/*.dbmdl
13 | **/*.jfm
14 | **/azds.yaml
15 | **/bin
16 | **/charts
17 | **/docker-compose*
18 | **/Dockerfile*
19 | **/node_modules
20 | **/npm-debug.log
21 | **/obj
22 | **/secrets.dev.yaml
23 | **/values.dev.yaml
24 | LICENSE
25 | README.md
--------------------------------------------------------------------------------
/actions/sequester/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/actions/sequester/ImportIssues/GlobalUsings.cs:
--------------------------------------------------------------------------------
1 | global using Quest2GitHub;
2 | global using Quest2GitHub.Options;
3 |
--------------------------------------------------------------------------------
/actions/sequester/Quest2GitHub.Tests/GlobalUsings.cs:
--------------------------------------------------------------------------------
1 | global using Microsoft.Extensions.Configuration;
2 | global using Microsoft.Extensions.DependencyInjection;
3 | global using Microsoft.Extensions.Options;
4 | global using Quest2GitHub.Extensions;
5 | global using Quest2GitHub.Options;
6 | global using Xunit;
7 |
--------------------------------------------------------------------------------
/actions/sequester/Quest2GitHub.Tests/QuestWorkItemTests.cs:
--------------------------------------------------------------------------------
1 | using Quest2GitHub.Models;
2 |
3 | namespace Quest2GitHub.Tests;
4 |
5 | public class QuestWorkItemTests
6 | {
7 | [Theory]
8 | [InlineData("short title")]
9 | [InlineData("A really long title, in fact, it's so long that we know it will exceed the max length of 255 characters imposed by the Azure DevOps API, thus proving our point, and being truncated in the object's .ctor. Isn't programming fun?! Wow, this title is really long...I hope we're done typing soon.")]
10 | public void QuestItemConstructorEnsuresTitleIsTruncated(string title)
11 | {
12 | var sut = new QuestWorkItem
13 | {
14 | Id = 777,
15 | ParentWorkItemId = 100,
16 | ParentRelationIndex = 1,
17 | Title = title, // Truncated on init
18 | State = "Wisconsin 🧀",
19 | Description = "Test description",
20 | AreaPath = "Test/Area",
21 | IterationPath = "Test/Path",
22 | AssignedToId = Guid.NewGuid(),
23 | StoryPoints = 1,
24 | Priority = 1,
25 | Tags = []
26 | };
27 |
28 | Assert.True(sut.Title.Length < 256);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/actions/sequester/Quest2GitHub.Tests/quest-import.json:
--------------------------------------------------------------------------------
1 | {
2 | "ImportOptions": {
3 | "GitHubOrg": "org",
4 | "GitHubRepo": "repo",
5 | "AzureDevOps": {
6 | "Org": "org",
7 | "Project": "proj",
8 | "AreaPath": "path"
9 | },
10 | "ApiKeys": {
11 | "GitHubToken": "ght",
12 | "OSPOKey": "okey",
13 | "QuestKey": "qkey"
14 | },
15 | "ImportTriggerLabel": "trigger-import",
16 | "ImportedLabel": "imported",
17 | "ParentNodes": [
18 | {
19 | "Label": "okr-health",
20 | "ParentNodeId": 199082
21 | },
22 | {
23 | "Label": "dotnet-csharp/svc",
24 | "ParentNodeId": 227484
25 | }
26 | ],
27 | "DefaultParentNode": 228485
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/actions/sequester/Quest2GitHub/Extensions/ServiceCollectionExtensions.cs:
--------------------------------------------------------------------------------
1 | namespace Quest2GitHub.Extensions;
2 |
3 | public static class ServiceCollectionExtensions
4 | {
5 | public static IServiceCollection AddImportServices(
6 | this IServiceCollection services, IConfiguration importOptionsSection)
7 | {
8 | services.Configure(importOptionsSection);
9 |
10 | return services;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/actions/sequester/Quest2GitHub/GlobalUsings.cs:
--------------------------------------------------------------------------------
1 | global using DotNetDocs.Tools.GitHubCommunications;
2 | global using DotNetDocs.Tools.GraphQLQueries;
3 | global using Microsoft.DotnetOrg.Ospo;
4 | global using Microsoft.Extensions.Configuration;
5 | global using Microsoft.Extensions.DependencyInjection;
6 | global using Quest2GitHub.AzureDevOpsCommunications;
7 | global using Quest2GitHub.Extensions;
8 | global using Quest2GitHub.Models;
9 | global using Quest2GitHub.Options;
10 | global using System.Net.Http.Headers;
11 | global using System.Net.Mime;
12 | global using System.Text;
13 | global using System.Text.Json;
14 | global using System.Text.Json.Serialization;
--------------------------------------------------------------------------------
/actions/sequester/Quest2GitHub/Models/QuestIteration.cs:
--------------------------------------------------------------------------------
1 | namespace Quest2GitHub.Models;
2 |
3 | public class QuestIteration
4 | {
5 | public required int Id { get; init; }
6 | public required Guid Identifier { get; init; }
7 | public required string Name { get; init; }
8 | public required string Path { get; init; }
9 |
10 | public bool IsInSemester(string semesterName) => Path.Contains(semesterName);
11 |
12 | public static QuestIteration CurrentIteration(IEnumerable iterations)
13 | {
14 | var currentYear = int.Parse(DateTime.Now.ToString("yyyy"));
15 | var currentMonth = DateTime.Now.ToString("MMM");
16 | var iteration = IssueExtensions.ProjectIteration(currentMonth, currentYear, iterations);
17 | return iteration ?? throw new InvalidOperationException("No current iteration found.");
18 | }
19 |
20 | public static QuestIteration FutureIteration(IEnumerable iterations)
21 | => iterations.Single(sprint => sprint.Name is "Future");
22 |
23 | override public string ToString() => $"{Identifier} {Id} {Name} ({Path})";
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/actions/sequester/Quest2GitHub/Options/LocalFileReader.cs:
--------------------------------------------------------------------------------
1 | namespace Quest2GitHub.Options;
2 |
3 | public sealed class LocalFileReader
4 | {
5 | public async Task ReadOptionsAsync(string path)
6 | {
7 | try
8 | {
9 | var json = await File.ReadAllTextAsync(path);
10 | var options = JsonSerializer.Deserialize(json);
11 |
12 | options.WriteValuesToConsole();
13 | if (options is not null)
14 | {
15 | options = options with
16 | {
17 | ApiKeys = EnvironmentVariableReader.GetApiKeys()
18 | };
19 | }
20 |
21 | return options;
22 | }
23 | catch (Exception ex)
24 | {
25 | Console.Error.WriteLine($"Attempted reading: {path}, {ex}");
26 | }
27 |
28 | return null;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/actions/sequester/Quest2GitHub/Quest2GitHub.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net9.0
5 | enable
6 | enable
7 | 2.1.0.0
8 | 2.1.0.0
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/actions/sequester/action.yml:
--------------------------------------------------------------------------------
1 | name: Quest synchronizer
2 | description: Automatically synchronize GitHub issues with Quest (Azure DevOps).
3 | author: 'Bill Wagner'
4 | branding:
5 | icon: refresh-cw
6 | color: purple
7 | inputs:
8 | org:
9 | description: 'The organization the repo belongs to. Assign from github.repository_owner. Example, "dotnet".'
10 | default: 'dotnet'
11 | repo:
12 | description: 'The repository name. Example, "docs".'
13 | default: 'docs'
14 | issue:
15 | description: 'An optional issue number to target when being triggered for a single issue.'
16 | branch:
17 | description: 'The branch to target. Assign from github.ref_name. Example, "main".'
18 | default: 'main'
19 | duration:
20 | description: 'How many days updates to process. Issues must have been updated in that many recent days for processing.'
21 | default: '5'
22 |
23 | runs:
24 | using: docker
25 | image: ../../sequester.Dockerfile
26 | args:
27 | - '--org'
28 | - ${{ inputs.org }}
29 | - '--repo'
30 | - ${{ inputs.repo }}
31 | - '--issue'
32 | - ${{ inputs.issue }}
33 | - '--branch'
34 | - ${{ inputs.branch }}
35 | - '--duration'
36 | - ${{ inputs.duration }}
37 |
--------------------------------------------------------------------------------
/actions/status-checker/.eslintignore:
--------------------------------------------------------------------------------
1 | dist/
2 | lib/
3 | node_modules/
4 | jest.config.js
5 |
--------------------------------------------------------------------------------
/actions/status-checker/.gitattributes:
--------------------------------------------------------------------------------
1 | dist/** -diff linguist-generated=true
--------------------------------------------------------------------------------
/actions/status-checker/.prettierignore:
--------------------------------------------------------------------------------
1 | dist/
2 | lib/
3 | node_modules/
--------------------------------------------------------------------------------
/actions/status-checker/__tests__/3/three.md:
--------------------------------------------------------------------------------
1 | # THREE
2 |
--------------------------------------------------------------------------------
/actions/status-checker/__tests__/file-heading-extractor.test.ts:
--------------------------------------------------------------------------------
1 | import { describe, expect, it } from "@jest/globals";
2 | import { getHeadingTextFrom } from "../src/file-heading-extractor";
3 |
4 | beforeAll(() => {
5 | process.env["GITHUB_REPOSITORY"] = "dotnet/docs";
6 | });
7 |
8 | describe("file-heading-extractor", () => {
9 | it("when calling getHeadingTextFrom correctly returns H1 value.", async () => {
10 | const path = "__tests__/sample.md";
11 | const actual = await getHeadingTextFrom(path);
12 | expect(actual).toBe("The heading `System.Console` class");
13 | });
14 |
15 | it("when calling getHeadingTextFrom correctly returns title value.", async () => {
16 | const path = "__tests__/no-heading.md";
17 | const actual = await getHeadingTextFrom(path);
18 | expect(actual).toBe("Phew, that worked!");
19 | });
20 | });
21 |
--------------------------------------------------------------------------------
/actions/status-checker/__tests__/main.test.ts:
--------------------------------------------------------------------------------
1 | import { wait } from "../src/wait";
2 | import { describe, expect, it } from "@jest/globals";
3 |
4 | describe("status-checker", () => {
5 | it("throws invalid number when given 'foo' string", async () => {
6 | const input = parseInt("foo", 10);
7 | await expect(wait(input)).rejects.toThrow("milliseconds not a number");
8 | });
9 |
10 | it("call to 'wait' actually waits 500 ms", async () => {
11 | const start = new Date();
12 | await wait(500);
13 | const end = new Date();
14 | var delta = Math.abs(end.getTime() - start.getTime());
15 | expect(delta).toBeGreaterThan(450);
16 | });
17 | });
18 |
--------------------------------------------------------------------------------
/actions/status-checker/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | clearMocks: true,
3 | moduleFileExtensions: ['js', 'ts'],
4 | testEnvironment: 'node',
5 | testMatch: ['**/*.test.ts'],
6 | testRunner: 'jest-circus/runner',
7 | transform: {
8 | '^.+\\.ts$': 'ts-jest'
9 | },
10 | verbose: true
11 | }
--------------------------------------------------------------------------------
/actions/status-checker/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "typescript-action",
3 | "version": "1.0.0",
4 | "private": true,
5 | "description": "TypeScript template action",
6 | "main": "lib/main.js",
7 | "scripts": {
8 | "build": "tsc",
9 | "format": "prettier --write **/*.ts",
10 | "format-check": "prettier --check **/*.ts",
11 | "package": "ncc build --source-map --license licenses.txt",
12 | "test": "jest --detectOpenHandles",
13 | "all": "npm run build && npm run format && npm run package && npm test"
14 | },
15 | "repository": {
16 | "type": "git",
17 | "url": "git+https://github.com/actions/typescript-action.git"
18 | },
19 | "keywords": [
20 | "actions",
21 | "node",
22 | "setup"
23 | ],
24 | "author": "",
25 | "license": "MIT",
26 | "dependencies": {
27 | "@actions/core": "^1.10.0",
28 | "@actions/github": "^6.0.0"
29 | },
30 | "devDependencies": {
31 | "@types/jest": "^29.2.6",
32 | "@types/node": "^18.11.18",
33 | "@vercel/ncc": "^0.36.0",
34 | "jest": "^29.3.1",
35 | "jest-circus": "^29.3.1",
36 | "js-yaml": "^4.1.0",
37 | "prettier": "^2.8.3",
38 | "ts-jest": "^29.0.5",
39 | "typescript": "^4.9.4"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/actions/status-checker/src/main.ts:
--------------------------------------------------------------------------------
1 | import { wait } from "./wait";
2 | import { isSuccessStatus } from "./status-checker";
3 | import { setFailed } from "@actions/core";
4 | import { tryUpdatePullRequestBody } from "./pull-updater";
5 | import { workflowInput } from "./types/WorkflowInput";
6 |
7 | async function run(): Promise {
8 | try {
9 | const token: string = workflowInput.repoToken;
10 |
11 | // Wait 60 seconds before checking status check result.
12 | await wait(60000);
13 | console.log("Waited 60 seconds.");
14 |
15 | // When the status is passed, try to update the PR body.
16 | const isSuccess = await isSuccessStatus(token);
17 | if (isSuccess) {
18 | console.log("✅ Build status is good...");
19 | } else {
20 | console.log("❌ Build status has warnings or errors!");
21 | }
22 | if (workflowInput.mode === "preview") {
23 | await tryUpdatePullRequestBody(token);
24 | }
25 | } catch (error: unknown) {
26 | const e = error as Error;
27 | setFailed(e.message);
28 | }
29 | }
30 |
31 | run();
32 |
--------------------------------------------------------------------------------
/actions/status-checker/src/types/ChangeType.ts:
--------------------------------------------------------------------------------
1 | export type ChangeType =
2 | | "ADDED"
3 | | "CHANGED"
4 | | "COPIED"
5 | | "DELETED"
6 | | "MODIFIED"
7 | | "RENAMED";
8 |
--------------------------------------------------------------------------------
/actions/status-checker/src/types/FileChange.ts:
--------------------------------------------------------------------------------
1 | import { ChangeType } from "./ChangeType";
2 |
3 | export type FileChange = {
4 | readonly additions: number;
5 | readonly changeType: ChangeType;
6 | readonly deletions: number;
7 | readonly path: string;
8 | };
9 |
--------------------------------------------------------------------------------
/actions/status-checker/src/types/Mode.ts:
--------------------------------------------------------------------------------
1 | export type Mode = "preview" | "warning";
2 |
--------------------------------------------------------------------------------
/actions/status-checker/src/types/NodeOf.ts:
--------------------------------------------------------------------------------
1 | export type NodeOf = {
2 | readonly node: T;
3 | };
4 |
--------------------------------------------------------------------------------
/actions/status-checker/src/types/PageInfo.ts:
--------------------------------------------------------------------------------
1 | export type PageInfo = {
2 | hasNextPage: boolean;
3 | endCursor: string;
4 | };
5 |
--------------------------------------------------------------------------------
/actions/status-checker/src/types/Pull.ts:
--------------------------------------------------------------------------------
1 | import { FileChange } from "./FileChange";
2 | import { NodeOf } from "./NodeOf";
3 | import { PageInfo } from "./PageInfo";
4 | import { PullRequestState } from "./PullRequestState";
5 |
6 | export type Pull = {
7 | readonly body: string;
8 | readonly checksUrl: string;
9 | readonly changedFiles: number;
10 | readonly state: PullRequestState;
11 | readonly files: {
12 | readonly pageInfo: PageInfo;
13 | readonly edges: NodeOf[];
14 | };
15 | };
16 |
--------------------------------------------------------------------------------
/actions/status-checker/src/types/PullRequestDetails.ts:
--------------------------------------------------------------------------------
1 | import { Pull } from "./Pull";
2 |
3 | export type PullRequestDetails = {
4 | readonly repository: {
5 | readonly pullRequest: Pull;
6 | };
7 | };
8 |
--------------------------------------------------------------------------------
/actions/status-checker/src/types/PullRequestState.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * See https://docs.github.com/graphql/reference/enums#pullrequeststate
3 | */
4 | export type PullRequestState = "CLOSED" | "MERGED" | "OPEN";
5 |
--------------------------------------------------------------------------------
/actions/status-checker/src/wait.ts:
--------------------------------------------------------------------------------
1 | export async function wait(milliseconds: number): Promise {
2 | return new Promise((resolve) => {
3 | if (isNaN(milliseconds)) {
4 | throw new Error("milliseconds not a number");
5 | }
6 |
7 | setTimeout(() => resolve("done!"), milliseconds);
8 | });
9 | }
10 |
--------------------------------------------------------------------------------
/actions/status-checker/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ES2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
4 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
5 | "outDir": "./lib", /* Redirect output structure to the directory. */
6 | "rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
7 | "strict": true, /* Enable all strict type-checking options. */
8 | "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
9 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
10 | },
11 | "exclude": ["node_modules", "**/*.test.ts"]
12 | }
13 |
--------------------------------------------------------------------------------
/cleanrepo.Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0 as build-env
2 | # Copy everything and publish the release (publish implicitly restores and builds)
3 | WORKDIR /app
4 | COPY . ./
5 | RUN dotnet publish "./cleanrepo/CleanRepo.csproj" -c Release -o out --no-self-contained
6 |
7 | # Relayer the .NET SDK, anew with the build output
8 | FROM mcr.microsoft.com/dotnet/sdk:9.0
9 | COPY --from=build-env /app/out .
10 | ENTRYPOINT [ "dotnet", "/CleanRepo.dll" ]
11 | # RUN chmod +x /multiplexer.sh
12 | # ENTRYPOINT [ "/bin/bash", "/multiplexer.sh" ]
13 |
--------------------------------------------------------------------------------
/cleanrepo/CleanRepo.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | Exe
4 | net9.0
5 | enable
6 | enable
7 | Linux
8 |
9 |
10 |
11 |
12 |
13 |
14 | Always
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | PreserveNewest
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/cleanrepo/GlobalSuppressions.cs:
--------------------------------------------------------------------------------
1 |
2 | // This file is used by Code Analysis to maintain SuppressMessage
3 | // attributes that are applied to this project.
4 | // Project-level suppressions either have no target or are given
5 | // a specific target and scoped to a namespace, type, member, etc.
6 |
7 | using System.Diagnostics.CodeAnalysis;
8 |
9 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1307:Specify StringComparison", Justification = "", Scope = "namespace", Target = "CleanRepo")]
10 | [assembly: System.Diagnostics.CodeAnalysis.SuppressMessage("Globalization", "CA1304:Specify CultureInfo", Justification = "", Scope = "namespace", Target = "CleanRepo")]
11 | [assembly: SuppressMessage("Globalization", "CA1307:Specify StringComparison", Justification = "", Scope = "member", Target = "~M:CleanRepo.DocFxRepo.ProcessImagePath(System.String,System.IO.FileInfo)")]
12 |
--------------------------------------------------------------------------------
/cleanrepo/Options.cs:
--------------------------------------------------------------------------------
1 | namespace CleanRepo;
2 |
3 | class Options
4 | {
5 | public string? DocFxDirectory { get; set; }
6 | public string? TargetDirectory { get; set; }
7 | public string? UrlBasePath { get; set; }
8 | public bool Delete { get; set; } = true;
9 | public bool XmlSource { get; set; } = false;
10 | public string? Function { get; set; }
11 | public string? OcrModelDirectory { get; set; }
12 | public string? FilterTextJsonFile { get; set; }
13 | public List? LimitReferencingDirectories { get; set; }
14 | }
15 |
--------------------------------------------------------------------------------
/cleanrepo/Redirect.cs:
--------------------------------------------------------------------------------
1 | namespace CleanRepo;
2 |
3 | internal class Redirect
4 | {
5 | public string? source_path { get; set; } = null;
6 | public string? source_path_from_root { get; set; } = null;
7 | public string? source_path_absolute { get; set; } = null;
8 | public string? redirect_url { get; set; }
9 | public bool? redirect_document_id { get; set; } = null;
10 | }
11 |
--------------------------------------------------------------------------------
/cleanrepo/RedirectionFile.cs:
--------------------------------------------------------------------------------
1 | namespace CleanRepo;
2 |
3 | internal class RedirectionFile
4 | {
5 | public IList? redirections { get; set; }
6 | }
7 |
--------------------------------------------------------------------------------
/cleanrepo/appSettings.json:
--------------------------------------------------------------------------------
1 | {
2 | "Options": {
3 | "DocFxDirectory": null,
4 | "TargetDirectory": null,
5 | "UrlBasePath": "/dotnet",
6 | "Function": "FindOrphanedArticles",
7 | "OcrModelDirectory": null,
8 | "FilterTextJsonFile": null,
9 | "Delete": true,
10 | "XmlSource": false
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/quest-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "AzureDevOps": {
3 | "Org": "msft-skilling",
4 | "Project": "Content",
5 | "AreaPath": "Production\\Core AI\\DotNet and more\\dotnet"
6 | },
7 | "ImportTriggerLabel": ":world_map: reQUEST",
8 | "ImportedLabel": ":pushpin: seQUESTered",
9 | "ParentNodes": [
10 | {
11 | "Semester": "Selenium",
12 | "ParentNodeId": 286035
13 | },
14 | {
15 | "Semester": "Bromine",
16 | "ParentNodeId": 405108
17 | }
18 | ],
19 | "DefaultParentNode": 405108
20 | }
--------------------------------------------------------------------------------
/sequester.Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0 as build-env
2 | # Copy everything and publish the release (publish implicitly restores and builds)
3 | WORKDIR /app
4 | COPY . ./
5 | RUN dotnet publish "actions/sequester/ImportIssues/ImportIssues.csproj" -c Release -o out --no-self-contained
6 |
7 | # Relayer the .NET SDK, anew with the build output
8 | FROM mcr.microsoft.com/dotnet/sdk:9.0
9 | COPY --from=build-env /app/out .
10 | ENTRYPOINT [ "dotnet", "/ImportIssues.dll" ]
11 |
--------------------------------------------------------------------------------
/smalltest.Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0 as build-env
2 | # Copy everything and publish the release (publish implicitly restores and builds)
3 | WORKDIR /app
4 | COPY . ./
5 | RUN dotnet publish "SmallRepo/SmallRepo.csproj" -c Release -o out --no-self-contained
6 |
7 | # Relayer the .NET SDK, anew with the build output
8 | FROM mcr.microsoft.com/dotnet/sdk:9.0
9 | COPY --from=build-env /app/out .
10 | ENTRYPOINT [ "dotnet", "/SmallRepo.dll" ]
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations.Generators/PullRequestSimulations.Generators.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.0
5 | false
6 | true
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | $(GetTargetPathDependsOn);GetDependencyTargetPaths
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/Usings.cs:
--------------------------------------------------------------------------------
1 | global using Microsoft.VisualStudio.TestTools.UnitTesting;
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/bad/lots-o-projects/extensions/linq.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | true
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/bad/lots-o-projects/partition_not_in_sln/Program.cs:
--------------------------------------------------------------------------------
1 | int chunkNumber = 1;
2 | foreach (int[] chunk in Enumerable.Range(0, 8).Chunk(3))
3 | {
4 | Console.WriteLine($"Chunk {chunkNumber++}:");
5 | foreach (int item in chunk)
6 | {
7 | Console.WriteLine($" {item}");
8 | }
9 |
10 | Console.WriteLine();
11 | }
12 | // This code produces the following output:
13 | // Chunk 1:
14 | // 0
15 | // 1
16 | // 2
17 | //
18 | //Chunk 2:
19 | // 3
20 | // 4
21 | // 5
22 | //
23 | //Chunk 3:
24 | // 6
25 | // 7
26 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/bad/lots-o-projects/partition_not_in_sln/partition.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | true
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/bad/patternmatching/childfolder/other.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/bad/patternmatching/patternmatching.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/bad/samefolder/project1.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/bad/samefolder/project2.vbproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/bad/sln_no_proj/some_code/Planet.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | record Planet(
4 | string Name,
5 | PlanetType Type,
6 | int OrderFromSun)
7 | {
8 | public static readonly Planet Mercury =
9 | new(nameof(Mercury), PlanetType.Rock, 1);
10 |
11 | public static readonly Planet Venus =
12 | new(nameof(Venus), PlanetType.Rock, 2);
13 |
14 | public static readonly Planet Earth =
15 | new(nameof(Earth), PlanetType.Rock, 3);
16 |
17 | public static readonly Planet Mars =
18 | new(nameof(Mars), PlanetType.Rock, 4);
19 |
20 | public static readonly Planet Jupiter =
21 | new(nameof(Jupiter), PlanetType.Gas, 5);
22 |
23 | public static readonly Planet Saturn =
24 | new(nameof(Saturn), PlanetType.Gas, 6);
25 |
26 | public static readonly Planet Uranus =
27 | new(nameof(Uranus), PlanetType.Liquid, 7);
28 |
29 | public static readonly Planet Neptune =
30 | new(nameof(Neptune), PlanetType.Liquid, 8);
31 |
32 | // Yes, I know... not technically a planet anymore
33 | public static readonly Planet Pluto =
34 | new(nameof(Pluto), PlanetType.Ice, 9);
35 | }
36 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/bad/sln_no_proj/some_code/PlanetType.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | enum PlanetType
4 | {
5 | Rock,
6 | Ice,
7 | Gas,
8 | Liquid
9 | };
10 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/bad/sln_no_proj/some_code/Program.DistinctBy.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | public static partial class Program
4 | {
5 | internal static void DistinctByExample()
6 | {
7 | Console.WriteLine("DistinctBy:");
8 |
9 | //
10 | Planet[] planets =
11 | {
12 | Planet.Mercury,
13 | Planet.Venus,
14 | Planet.Earth,
15 | Planet.Mars,
16 | Planet.Jupiter,
17 | Planet.Saturn,
18 | Planet.Uranus,
19 | Planet.Neptune,
20 | Planet.Pluto
21 | };
22 | //
23 |
24 | //
25 | foreach (Planet planet in planets.DistinctBy(p => p.Type))
26 | {
27 | Console.WriteLine(planet);
28 | }
29 |
30 | // This code produces the following output:
31 | // Planet { Name = Mercury, Type = Rock, OrderFromSun = 1 }
32 | // Planet { Name = Jupiter, Type = Gas, OrderFromSun = 5 }
33 | // Planet { Name = Uranus, Type = Liquid, OrderFromSun = 7 }
34 | // Planet { Name = Pluto, Type = Ice, OrderFromSun = 9 }
35 | //
36 |
37 | Console.WriteLine();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/bad/sln_no_proj/some_code/Program.ExceptBy.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | public static partial class Program
4 | {
5 | internal static void ExceptByExample()
6 | {
7 | Console.WriteLine("ExceptBy:");
8 |
9 | //
10 | Planet[] planets =
11 | {
12 | Planet.Mercury,
13 | Planet.Venus,
14 | Planet.Earth,
15 | Planet.Jupiter
16 | };
17 |
18 | Planet[] morePlanets =
19 | {
20 | Planet.Mercury,
21 | Planet.Earth,
22 | Planet.Mars,
23 | Planet.Jupiter
24 | };
25 | //
26 |
27 | //
28 | // A shared "keySelector"
29 | static string PlanetNameSelector(Planet planet) => planet.Name;
30 |
31 | foreach (Planet planet in
32 | planets.ExceptBy(
33 | morePlanets.Select(PlanetNameSelector), PlanetNameSelector))
34 | {
35 | Console.WriteLine(planet);
36 | }
37 |
38 | // This code produces the following output:
39 | // Planet { Name = Venus, Type = Rock, OrderFromSun = 2 }
40 | //
41 |
42 | Console.WriteLine();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/bad/sln_no_proj/some_code/Program.cs:
--------------------------------------------------------------------------------
1 | using SolarSystem;
2 |
3 | Program.DistinctByExample();
4 | Program.ExceptByExample();
5 | Program.IntersectByExample();
6 | Program.UnionByExample();
7 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/finished/toll-calculator/ExternalSystems.cs:
--------------------------------------------------------------------------------
1 | namespace ConsumerVehicleRegistration
2 | {
3 | public class Car
4 | {
5 | public int Passengers { get; set; }
6 | }
7 | }
8 |
9 | namespace CommercialRegistration
10 | {
11 | public class DeliveryTruck
12 | {
13 | public int GrossWeightClass { get; set; }
14 | }
15 | }
16 |
17 | namespace LiveryRegistration
18 | {
19 | public class Taxi
20 | {
21 | public int Fares { get; set; }
22 | }
23 |
24 | public class Bus
25 | {
26 | public int Capacity { get; set; }
27 | public int Riders { get; set; }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/finished/toll-calculator/toll-calculator.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | toll_calculator
7 | enable
8 | enable
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/start/toll-calculator/ExternalSystems.cs:
--------------------------------------------------------------------------------
1 | namespace ConsumerVehicleRegistration
2 | {
3 | public class Car
4 | {
5 | public int Passengers { get; set; }
6 | }
7 | }
8 |
9 | namespace CommercialRegistration
10 | {
11 | public class DeliveryTruck
12 | {
13 | public int GrossWeightClass { get; set; }
14 | }
15 | }
16 |
17 | namespace LiveryRegistration
18 | {
19 | public class Taxi
20 | {
21 | public int Fares { get; set; }
22 | }
23 |
24 | public class Bus
25 | {
26 | public int Capacity { get; set; }
27 | public int Riders { get; set; }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/start/toll-calculator/toll-calculator.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | toll_calculator
8 | enable
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/cpp/MyForm.cpp:
--------------------------------------------------------------------------------
1 | #include "MyForm.h"
2 |
3 | using namespace System;
4 | using namespace System::Windows::Forms;
5 | [STAThreadAttribute]
6 |
7 | void main(array^ args) {
8 | Application::SetCompatibleTextRenderingDefault(false);
9 | Application::EnableVisualStyles();
10 | project::MyForm frm;
11 | Application::Run(%frm);
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/cpp/Student.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | namespace project {
3 |
4 | using namespace System;
5 | using namespace System::Collections;
6 | public ref class Student
7 | {
8 | private:
9 | ArrayList^ _studentSubjects = gcnew ArrayList();
10 | public:
11 | String^ StudentName = "";
12 |
13 | ArrayList^ StudentSubjects = _studentSubjects;
14 |
15 | Student(String^ studentName)
16 | {
17 | StudentName = studentName;
18 | }
19 | };
20 | };
21 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/cpp/Subject.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | namespace project {
3 | using namespace System;
4 | using namespace System::Collections;
5 |
6 | public ref class Subject
7 | {
8 | private:
9 | ArrayList^ _subjectTextbooks = gcnew ArrayList();
10 | public:
11 | String^ SubjectID = "";
12 |
13 | ArrayList^ SubjectTextbooks = _subjectTextbooks;
14 |
15 | Subject(String^ subjectID)
16 | {
17 | SubjectID = subjectID;
18 | }
19 | };
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/cpp/TextBook.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | namespace project {
3 | using namespace System;
4 | using namespace System::Collections;
5 |
6 | public ref class TextBook
7 | {
8 | public:
9 | String^ TextBookID = "";
10 |
11 | TextBook(String^ textBookID)
12 | {
13 | TextBookID = textBookID;
14 | }
15 | };
16 | }
17 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/cpp/snippets.5000.json:
--------------------------------------------------------------------------------
1 | {
2 | "host": "dotnet",
3 | "expectederrors": [
4 | {
5 | "file": "snippets\\good\\deeper-path\\three_projs\\cpp\\project.vcxproj",
6 | "line": 33,
7 | "column": 3,
8 | "error": "MSB4019"
9 | }
10 | ]
11 | }
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/cs/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using System.Windows.Forms;
6 |
7 | namespace project
8 | {
9 | static class Program
10 | {
11 | ///
12 | /// The main entry point for the application.
13 | ///
14 | [STAThread]
15 | static void Main()
16 | {
17 | Application.EnableVisualStyles();
18 | Application.SetCompatibleTextRenderingDefault(false);
19 | Application.Run(new Form1());async;
20 | }
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/cs/Student.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 |
3 | namespace project
4 | {
5 | // The basic Student class.
6 | public class Student
7 | {
8 | protected ArrayList _studentSubjects = new ArrayList();
9 |
10 | public Student(string studentName)
11 | {
12 | StudentName = studentName;
13 | }
14 |
15 | public string StudentName { get; set; } = "";
16 |
17 | public ArrayList StudentSubjects => _studentSubjects;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/cs/Subject.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 |
3 | namespace project
4 | {
5 | // The basic student Subject class.
6 | public class Subject
7 | {
8 | protected ArrayList _subjectTextbooks = new ArrayList();
9 |
10 | public Subject(string subjectID)
11 | {
12 | SubjectID = subjectID;
13 | }
14 |
15 | public string SubjectID { get; set; } = "";
16 |
17 | public ArrayList SubjectTextbooks => _subjectTextbooks;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/cs/TextBook.cs:
--------------------------------------------------------------------------------
1 | namespace project
2 | {
3 | public class TextBook
4 | {
5 |
6 | public TextBook(string textBookID)
7 | {
8 | TextBookID = textBookID;
9 | }
10 |
11 | public string TextBookID { get; set; } = "";
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/cs/snippets.5000.json:
--------------------------------------------------------------------------------
1 | {
2 | "host": "dotnet",
3 | "expectederrors": [
4 | {
5 | "file": "snippets\\good\\deeper-path\\three_projs\\cs\\Program.cs",
6 | "line": 19,
7 | "error": "CS0201"
8 | },
9 | {
10 | "file": "snippets\\good\\deeper-path\\three_projs\\cs\\program.cs",
11 | "line": 19,
12 | "error": "CS0103"
13 | }
14 | ]
15 | }
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/vb/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/vb/My Project/Application.myapp:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 | Form1
5 | false
6 | 0
7 | true
8 | 0
9 | 0
10 | true
11 |
12 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/vb/My Project/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/vb/Student.vb:
--------------------------------------------------------------------------------
1 | Namespace project
2 | Public Class Student
3 | Protected _studentSubjects As ArrayList = New ArrayList()
4 |
5 | Public Sub New(studentName As String)
6 | Me.StudentName = studentName
7 | End Sub
8 |
9 | Public Property StudentName As String = ""
10 |
11 | Public ReadOnly Property StudentSubjects As ArrayList
12 | Get
13 | Return _studentSubjects
14 | End Get
15 | End Property
16 | End Class
17 | End Namespace
18 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/vb/Subject.vb:
--------------------------------------------------------------------------------
1 | Namespace project
2 | Public Class Subject
3 | Protected _subjectTextbooks As ArrayList = New ArrayList()
4 |
5 | Public Sub New(ByVal subjectID As String)
6 | Me.SubjectID = subjectID
7 | End Sub
8 |
9 | Public Property SubjectID As String = ""
10 |
11 | Public ReadOnly Property SubjectTextbooks As ArrayList
12 | Get
13 | Return _subjectTextbooks
14 | End Get
15 | End Property
16 | End Class
17 | End Namespace
18 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/deeper-path/three_projs/vb/TextBook.vb:
--------------------------------------------------------------------------------
1 | Namespace project
2 | Public Class TextBook
3 | Public Sub New(textBookID As String)
4 | Me.TextBookID = textBookID
5 | End Sub
6 |
7 | Public Property TextBookID As String = ""
8 | End Class
9 | End Namespace
10 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/normal/asandis/asandis.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/normal/csharp_project/Program.cs:
--------------------------------------------------------------------------------
1 | // See https://aka.ms/new-console-template for more information
2 | Console.WriteLine("Hello, World!");
3 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/normal/csharp_project/app1.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net7.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/normal/csharp_project/snippets.5000.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet/docs-tools/e88a4c229f2fc2dbe5cfa3ffabbcef8489ffba50/snippets5000/PullRequestSimulations/snippets/good/normal/csharp_project/snippets.5000.json
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/normal/deleted_code/snippets.5000.json:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dotnet/docs-tools/e88a4c229f2fc2dbe5cfa3ffabbcef8489ffba50/snippets5000/PullRequestSimulations/snippets/good/normal/deleted_code/snippets.5000.json
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/normal/nullablepatternmatching/nullablepatternmatching.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/normal/patternmatching/patternmatching.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/normal/vb_project/Program.vb:
--------------------------------------------------------------------------------
1 | Imports System
2 |
3 | Module Program
4 | Sub Main(args As String())
5 | Console.WriteLine("Hello World!")
6 | End Sub
7 | End Module
8 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/normal/vb_project/app1.vbproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | vb_project
6 | net7.0
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/lots-o-projects/extensions/linq.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | true
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/lots-o-projects/partition/Program.cs:
--------------------------------------------------------------------------------
1 | int chunkNumber = 1;
2 | foreach (int[] chunk in Enumerable.Range(0, 8).Chunk(3))
3 | {
4 | Console.WriteLine($"Chunk {chunkNumber++}:");
5 | foreach (int item in chunk)
6 | {
7 | Console.WriteLine($" {item}");
8 | }
9 |
10 | Console.WriteLine();
11 | }
12 | // This code produces the following output:
13 | // Chunk 1:
14 | // 0
15 | // 1
16 | // 2
17 | //
18 | //Chunk 2:
19 | // 3
20 | // 4
21 | // 5
22 | //
23 | //Chunk 3:
24 | // 6
25 | // 7
26 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/lots-o-projects/partition/partition.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | true
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/lots-o-projects/projection/Program.ZipResult.cs:
--------------------------------------------------------------------------------
1 | public static partial class Program
2 | {
3 | internal static void ZipResultExample(
4 | IEnumerable numbers,
5 | IEnumerable letters)
6 | {
7 | Console.WriteLine("Zip (TFirst, TSecond, Func):");
8 |
9 | //
10 | foreach (string result in
11 | numbers.Zip(letters, (number, letter) => $"{number} = {letter} ({(int)letter})"))
12 | {
13 | Console.WriteLine(result);
14 | }
15 | // This code produces the following output:
16 | // 1 = A (65)
17 | // 2 = B (66)
18 | // 3 = C (67)
19 | // 4 = D (68)
20 | // 5 = E (69)
21 | // 6 = F (70)
22 | //
23 |
24 | Console.WriteLine();
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/lots-o-projects/projection/Program.ZipTriple.cs:
--------------------------------------------------------------------------------
1 | public static partial class Program
2 | {
3 | internal static void ZipTripleExample(
4 | IEnumerable numbers,
5 | IEnumerable letters,
6 | IEnumerable emoji)
7 | {
8 | Console.WriteLine("Zip (TFirst, TSecond, TThird):");
9 |
10 | //
11 | foreach ((int number, char letter, string em) in numbers.Zip(letters, emoji))
12 | {
13 | Console.WriteLine(
14 | $"Number: {number} is zipped with letter: '{letter}' and emoji: {em}");
15 | }
16 | // This code produces the following output:
17 | // Number: 1 is zipped with letter: 'A' and emoji: 🤓
18 | // Number: 2 is zipped with letter: 'B' and emoji: 🔥
19 | // Number: 3 is zipped with letter: 'C' and emoji: 🎉
20 | // Number: 4 is zipped with letter: 'D' and emoji: 👀
21 | // Number: 5 is zipped with letter: 'E' and emoji: ⭐
22 | // Number: 6 is zipped with letter: 'F' and emoji: 💜
23 | //
24 |
25 | Console.WriteLine();
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/lots-o-projects/projection/Program.ZipTuple.cs:
--------------------------------------------------------------------------------
1 | public static partial class Program
2 | {
3 | internal static void ZipTupleExample(
4 | IEnumerable numbers,
5 | IEnumerable letters)
6 | {
7 | Console.WriteLine("Zip (TFirst, TSecond):");
8 |
9 | //
10 | foreach ((int number, char letter) in numbers.Zip(letters))
11 | {
12 | Console.WriteLine($"Number: {number} zipped with letter: '{letter}'");
13 | }
14 | // This code produces the following output:
15 | // Number: 1 zipped with letter: 'A'
16 | // Number: 2 zipped with letter: 'B'
17 | // Number: 3 zipped with letter: 'C'
18 | // Number: 4 zipped with letter: 'D'
19 | // Number: 5 zipped with letter: 'E'
20 | // Number: 6 zipped with letter: 'F'
21 | //
22 |
23 | Console.WriteLine();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/lots-o-projects/projection/Program.cs:
--------------------------------------------------------------------------------
1 | // See https://aka.ms/new-console-template for more information
2 |
3 | Console.OutputEncoding = System.Text.Encoding.UTF8;
4 |
5 | //
6 | // An int array with 7 elements.
7 | IEnumerable numbers = new[]
8 | {
9 | 1, 2, 3, 4, 5, 6, 7
10 | };
11 | // A char array with 6 elements.
12 | IEnumerable letters = new[]
13 | {
14 | 'A', 'B', 'C', 'D', 'E', 'F'
15 | };
16 | //
17 | //
18 | // A string array with 8 elements.
19 | IEnumerable emoji = new[]
20 | {
21 | "🤓", "🔥", "🎉", "👀", "⭐", "💜", "✔", "💯"
22 | };
23 | //
24 |
25 | Program.ZipTupleExample(numbers, letters);
26 | Program.ZipTripleExample(numbers, letters, emoji);
27 | Program.ZipResultExample(numbers, letters);
28 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/lots-o-projects/projection/projection.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | true
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/lots-o-projects/set-operators/Planet.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | record Planet(
4 | string Name,
5 | PlanetType Type,
6 | int OrderFromSun)
7 | {
8 | public static readonly Planet Mercury =
9 | new(nameof(Mercury), PlanetType.Rock, 1);
10 |
11 | public static readonly Planet Venus =
12 | new(nameof(Venus), PlanetType.Rock, 2);
13 |
14 | public static readonly Planet Earth =
15 | new(nameof(Earth), PlanetType.Rock, 3);
16 |
17 | public static readonly Planet Mars =
18 | new(nameof(Mars), PlanetType.Rock, 4);
19 |
20 | public static readonly Planet Jupiter =
21 | new(nameof(Jupiter), PlanetType.Gas, 5);
22 |
23 | public static readonly Planet Saturn =
24 | new(nameof(Saturn), PlanetType.Gas, 6);
25 |
26 | public static readonly Planet Uranus =
27 | new(nameof(Uranus), PlanetType.Liquid, 7);
28 |
29 | public static readonly Planet Neptune =
30 | new(nameof(Neptune), PlanetType.Liquid, 8);
31 |
32 | // Yes, I know... not technically a planet anymore
33 | public static readonly Planet Pluto =
34 | new(nameof(Pluto), PlanetType.Ice, 9);
35 | }
36 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/lots-o-projects/set-operators/PlanetType.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | enum PlanetType
4 | {
5 | Rock,
6 | Ice,
7 | Gas,
8 | Liquid
9 | };
10 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/lots-o-projects/set-operators/Program.DistinctBy.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | public static partial class Program
4 | {
5 | internal static void DistinctByExample()
6 | {
7 | Console.WriteLine("DistinctBy:");
8 |
9 | //
10 | Planet[] planets =
11 | {
12 | Planet.Mercury,
13 | Planet.Venus,
14 | Planet.Earth,
15 | Planet.Mars,
16 | Planet.Jupiter,
17 | Planet.Saturn,
18 | Planet.Uranus,
19 | Planet.Neptune,
20 | Planet.Pluto
21 | };
22 | //
23 |
24 | //
25 | foreach (Planet planet in planets.DistinctBy(p => p.Type))
26 | {
27 | Console.WriteLine(planet);
28 | }
29 |
30 | // This code produces the following output:
31 | // Planet { Name = Mercury, Type = Rock, OrderFromSun = 1 }
32 | // Planet { Name = Jupiter, Type = Gas, OrderFromSun = 5 }
33 | // Planet { Name = Uranus, Type = Liquid, OrderFromSun = 7 }
34 | // Planet { Name = Pluto, Type = Ice, OrderFromSun = 9 }
35 | //
36 |
37 | Console.WriteLine();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/lots-o-projects/set-operators/Program.ExceptBy.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | public static partial class Program
4 | {
5 | internal static void ExceptByExample()
6 | {
7 | Console.WriteLine("ExceptBy:");
8 |
9 | //
10 | Planet[] planets =
11 | {
12 | Planet.Mercury,
13 | Planet.Venus,
14 | Planet.Earth,
15 | Planet.Jupiter
16 | };
17 |
18 | Planet[] morePlanets =
19 | {
20 | Planet.Mercury,
21 | Planet.Earth,
22 | Planet.Mars,
23 | Planet.Jupiter
24 | };
25 | //
26 |
27 | //
28 | // A shared "keySelector"
29 | static string PlanetNameSelector(Planet planet) => planet.Name;
30 |
31 | foreach (Planet planet in
32 | planets.ExceptBy(
33 | morePlanets.Select(PlanetNameSelector), PlanetNameSelector))
34 | {
35 | Console.WriteLine(planet);
36 | }
37 |
38 | // This code produces the following output:
39 | // Planet { Name = Venus, Type = Rock, OrderFromSun = 2 }
40 | //
41 |
42 | Console.WriteLine();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/lots-o-projects/set-operators/Program.cs:
--------------------------------------------------------------------------------
1 | using SolarSystem;
2 |
3 | Program.DistinctByExample();
4 | Program.ExceptByExample();
5 | Program.IntersectByExample();
6 | Program.UnionByExample();
7 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/lots-o-projects/set-operators/set-operators.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | true
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/single-project/set-operators/Planet.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | record Planet(
4 | string Name,
5 | PlanetType Type,
6 | int OrderFromSun)
7 | {
8 | public static readonly Planet Mercury =
9 | new(nameof(Mercury), PlanetType.Rock, 1);
10 |
11 | public static readonly Planet Venus =
12 | new(nameof(Venus), PlanetType.Rock, 2);
13 |
14 | public static readonly Planet Earth =
15 | new(nameof(Earth), PlanetType.Rock, 3);
16 |
17 | public static readonly Planet Mars =
18 | new(nameof(Mars), PlanetType.Rock, 4);
19 |
20 | public static readonly Planet Jupiter =
21 | new(nameof(Jupiter), PlanetType.Gas, 5);
22 |
23 | public static readonly Planet Saturn =
24 | new(nameof(Saturn), PlanetType.Gas, 6);
25 |
26 | public static readonly Planet Uranus =
27 | new(nameof(Uranus), PlanetType.Liquid, 7);
28 |
29 | public static readonly Planet Neptune =
30 | new(nameof(Neptune), PlanetType.Liquid, 8);
31 |
32 | // Yes, I know... not technically a planet anymore
33 | public static readonly Planet Pluto =
34 | new(nameof(Pluto), PlanetType.Ice, 9);
35 | }
36 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/single-project/set-operators/PlanetType.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | enum PlanetType
4 | {
5 | Rock,
6 | Ice,
7 | Gas,
8 | Liquid
9 | };
10 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/single-project/set-operators/Program.DistinctBy.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | public static partial class Program
4 | {
5 | internal static void DistinctByExample()
6 | {
7 | Console.WriteLine("DistinctBy:");
8 |
9 | //
10 | Planet[] planets =
11 | {
12 | Planet.Mercury,
13 | Planet.Venus,
14 | Planet.Earth,
15 | Planet.Mars,
16 | Planet.Jupiter,
17 | Planet.Saturn,
18 | Planet.Uranus,
19 | Planet.Neptune,
20 | Planet.Pluto
21 | };
22 | //
23 |
24 | //
25 | foreach (Planet planet in planets.DistinctBy(p => p.Type))
26 | {
27 | Console.WriteLine(planet);
28 | }
29 |
30 | // This code produces the following output:
31 | // Planet { Name = Mercury, Type = Rock, OrderFromSun = 1 }
32 | // Planet { Name = Jupiter, Type = Gas, OrderFromSun = 5 }
33 | // Planet { Name = Uranus, Type = Liquid, OrderFromSun = 7 }
34 | // Planet { Name = Pluto, Type = Ice, OrderFromSun = 9 }
35 | //
36 |
37 | Console.WriteLine();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/single-project/set-operators/Program.ExceptBy.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | public static partial class Program
4 | {
5 | internal static void ExceptByExample()
6 | {
7 | Console.WriteLine("ExceptBy:");
8 |
9 | //
10 | Planet[] planets =
11 | {
12 | Planet.Mercury,
13 | Planet.Venus,
14 | Planet.Earth,
15 | Planet.Jupiter
16 | };
17 |
18 | Planet[] morePlanets =
19 | {
20 | Planet.Mercury,
21 | Planet.Earth,
22 | Planet.Mars,
23 | Planet.Jupiter
24 | };
25 | //
26 |
27 | //
28 | // A shared "keySelector"
29 | static string PlanetNameSelector(Planet planet) => planet.Name;
30 |
31 | foreach (Planet planet in
32 | planets.ExceptBy(
33 | morePlanets.Select(PlanetNameSelector), PlanetNameSelector))
34 | {
35 | Console.WriteLine(planet);
36 | }
37 |
38 | // This code produces the following output:
39 | // Planet { Name = Venus, Type = Rock, OrderFromSun = 2 }
40 | //
41 |
42 | Console.WriteLine();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/single-project/set-operators/Program.cs:
--------------------------------------------------------------------------------
1 | using SolarSystem;
2 |
3 | Program.DistinctByExample();
4 | Program.ExceptByExample();
5 | Program.IntersectByExample();
6 | Program.UnionByExample();
7 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/single-project/set-operators/set-operators.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | true
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/sln_odd_proj/file.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.0.31612.314
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Global
7 | GlobalSection(SolutionProperties) = preSolution
8 | HideSolutionNode = FALSE
9 | EndGlobalSection
10 | GlobalSection(ExtensibilityGlobals) = postSolution
11 | SolutionGuid = {DEB164F0-9F8F-4880-ACCF-994BE3CD9105}
12 | EndGlobalSection
13 | EndGlobal
14 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/sln_odd_proj/some_code/Planet.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | record Planet(
4 | string Name,
5 | PlanetType Type,
6 | int OrderFromSun)
7 | {
8 | public static readonly Planet Mercury =
9 | new(nameof(Mercury), PlanetType.Rock, 1);
10 |
11 | public static readonly Planet Venus =
12 | new(nameof(Venus), PlanetType.Rock, 2);
13 |
14 | public static readonly Planet Earth =
15 | new(nameof(Earth), PlanetType.Rock, 3);
16 |
17 | public static readonly Planet Mars =
18 | new(nameof(Mars), PlanetType.Rock, 4);
19 |
20 | public static readonly Planet Jupiter =
21 | new(nameof(Jupiter), PlanetType.Gas, 5);
22 |
23 | public static readonly Planet Saturn =
24 | new(nameof(Saturn), PlanetType.Gas, 6);
25 |
26 | public static readonly Planet Uranus =
27 | new(nameof(Uranus), PlanetType.Liquid, 7);
28 |
29 | public static readonly Planet Neptune =
30 | new(nameof(Neptune), PlanetType.Liquid, 8);
31 |
32 | // Yes, I know... not technically a planet anymore
33 | public static readonly Planet Pluto =
34 | new(nameof(Pluto), PlanetType.Ice, 9);
35 | }
36 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/sln_odd_proj/some_code/PlanetType.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | enum PlanetType
4 | {
5 | Rock,
6 | Ice,
7 | Gas,
8 | Liquid
9 | };
10 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/sln_odd_proj/some_code/Program.DistinctBy.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | public static partial class Program
4 | {
5 | internal static void DistinctByExample()
6 | {
7 | Console.WriteLine("DistinctBy:");
8 |
9 | //
10 | Planet[] planets =
11 | {
12 | Planet.Mercury,
13 | Planet.Venus,
14 | Planet.Earth,
15 | Planet.Mars,
16 | Planet.Jupiter,
17 | Planet.Saturn,
18 | Planet.Uranus,
19 | Planet.Neptune,
20 | Planet.Pluto
21 | };
22 | //
23 |
24 | //
25 | foreach (Planet planet in planets.DistinctBy(p => p.Type))
26 | {
27 | Console.WriteLine(planet);
28 | }
29 |
30 | // This code produces the following output:
31 | // Planet { Name = Mercury, Type = Rock, OrderFromSun = 1 }
32 | // Planet { Name = Jupiter, Type = Gas, OrderFromSun = 5 }
33 | // Planet { Name = Uranus, Type = Liquid, OrderFromSun = 7 }
34 | // Planet { Name = Pluto, Type = Ice, OrderFromSun = 9 }
35 | //
36 |
37 | Console.WriteLine();
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/sln_odd_proj/some_code/Program.ExceptBy.cs:
--------------------------------------------------------------------------------
1 | namespace SolarSystem;
2 |
3 | public static partial class Program
4 | {
5 | internal static void ExceptByExample()
6 | {
7 | Console.WriteLine("ExceptBy:");
8 |
9 | //
10 | Planet[] planets =
11 | {
12 | Planet.Mercury,
13 | Planet.Venus,
14 | Planet.Earth,
15 | Planet.Jupiter
16 | };
17 |
18 | Planet[] morePlanets =
19 | {
20 | Planet.Mercury,
21 | Planet.Earth,
22 | Planet.Mars,
23 | Planet.Jupiter
24 | };
25 | //
26 |
27 | //
28 | // A shared "keySelector"
29 | static string PlanetNameSelector(Planet planet) => planet.Name;
30 |
31 | foreach (Planet planet in
32 | planets.ExceptBy(
33 | morePlanets.Select(PlanetNameSelector), PlanetNameSelector))
34 | {
35 | Console.WriteLine(planet);
36 | }
37 |
38 | // This code produces the following output:
39 | // Planet { Name = Venus, Type = Rock, OrderFromSun = 2 }
40 | //
41 |
42 | Console.WriteLine();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/sln_odd_proj/some_code/Program.cs:
--------------------------------------------------------------------------------
1 | using SolarSystem;
2 |
3 | Program.DistinctByExample();
4 | Program.ExceptByExample();
5 | Program.IntersectByExample();
6 | Program.UnionByExample();
7 |
--------------------------------------------------------------------------------
/snippets5000/PullRequestSimulations/snippets/good/solutions/sln_odd_proj/some_code/project1.proj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/snippets5000/Snippets5000/DiscoveryResult.cs:
--------------------------------------------------------------------------------
1 | namespace Snippets5000
2 | {
3 | internal struct DiscoveryResult
4 | {
5 | public const int RETURN_GOOD = 0;
6 | public const int RETURN_NOPROJ = 1;
7 | public const int RETURN_TOOMANY = 2;
8 | public const int RETURN_SLN_NOPROJ = 3;
9 | public const int RETURN_SLN_PROJ_MISSING = 4;
10 |
11 | public const int RETURN_TEMP_SLNFOUND = 99;
12 |
13 | public readonly int Code { get; init; }
14 | public readonly string InputFile { get; init; }
15 | public readonly string DiscoveredFile { get; init; }
16 |
17 | public DiscoveryResult(int code, string inputFile, string discoveredFile)
18 | {
19 | Code = code;
20 | InputFile = inputFile;
21 | DiscoveredFile = discoveredFile;
22 | }
23 |
24 | public override string ToString() =>
25 | $"{Code}|{InputFile}|{DiscoveredFile}";
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/snippets5000/Snippets5000/Extensions.cs:
--------------------------------------------------------------------------------
1 | internal static class Extensions
2 | {
3 | // TRUE if "projectPath" is a child of one of the entries in folders
4 | internal static bool ContainedInOneOf(this string projectPath, IEnumerable folders)
5 | {
6 | foreach (var folder in folders)
7 | {
8 | if (projectPath.Contains(folder))
9 | {
10 | return true;
11 | }
12 | }
13 | return false;
14 | }
15 | }
16 |
17 |
18 |
--------------------------------------------------------------------------------
/snippets5000/Snippets5000/PullRequestSimulationsHelpers/ChangeItem.cs:
--------------------------------------------------------------------------------
1 | namespace PullRequestSimulations;
2 |
3 | ///
4 | /// A data type for the data.json file. Represents a pull request change item request.
5 | ///
6 | public readonly struct ChangeItem
7 | {
8 | ///
9 | /// The type of change associated with this item.
10 | ///
11 | public ChangeItemType ItemType { get; init; }
12 |
13 | ///
14 | /// The path to the file affected by this item.
15 | ///
16 | public string Path { get; init; }
17 |
18 | ///
19 | /// Creates a new change item with the specified values.
20 | ///
21 | /// The type of change.
22 | /// The path to the file affected by this item.
23 | public ChangeItem(ChangeItemType itemType, string path)
24 | {
25 | ItemType = itemType;
26 | Path = path;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/snippets5000/Snippets5000/PullRequestSimulationsHelpers/ChangeItemType.cs:
--------------------------------------------------------------------------------
1 | namespace PullRequestSimulations;
2 |
3 | ///
4 | /// A data type for the data.json file. Represents a pull request change item action.
5 | ///
6 | public enum ChangeItemType
7 | {
8 | ///
9 | /// Create a file.
10 | ///
11 | Create,
12 |
13 | ///
14 | /// Modify a file.
15 | ///
16 | Edit,
17 |
18 | ///
19 | /// Remove a file.
20 | ///
21 | Delete
22 | }
--------------------------------------------------------------------------------
/snippets5000/Snippets5000/PullRequestSimulationsHelpers/ExpectedResult.cs:
--------------------------------------------------------------------------------
1 | namespace PullRequestSimulations;
2 |
3 | ///
4 | /// A data type for the data.json file. A result from scanning a pull request change item.
5 | ///
6 | public readonly struct ExpectedResult
7 | {
8 | ///
9 | /// The result code from the scanner.
10 | ///
11 | /// These map to the constant values defined in the type.
12 | public int ResultCode { get; init; }
13 |
14 | ///
15 | /// The path to a project file
16 | ///
17 | public string DiscoveredProject { get; init; }
18 |
19 | ///
20 | /// Creates a new result with the specified code and project.
21 | ///
22 | /// The result code.
23 | /// The path to the project.
24 | public ExpectedResult(int resultCode, string discoveredProject)
25 | {
26 | ResultCode = resultCode;
27 | DiscoveredProject = discoveredProject;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/snippets5000/Snippets5000/Snippets5000.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net9.0
6 | enable
7 | enable
8 |
9 | 4.3.0.0
10 | Snippets 5000
11 | Andy De George
12 | Microsoft
13 |
14 | $(DefineConstants);LINUX
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/snippets5000/Snippets5000/TestingProjectList.cs:
--------------------------------------------------------------------------------
1 | namespace Snippets5000;
2 |
3 | ///
4 | /// This class is used to process an item from the data.json file in the MSTest project, simulating a GitHub PR.
5 | ///
6 | internal class TestingProjectList
7 | {
8 | private readonly string _testId;
9 | private readonly string _rootDir;
10 | private readonly string _testDataFile;
11 |
12 | internal TestingProjectList(string testId, string testDataFile, string rootDir)
13 | {
14 | _testId = testId;
15 | _rootDir = rootDir;
16 | _testDataFile = testDataFile;
17 | }
18 |
19 | internal IEnumerable GenerateBuildList()
20 | {
21 | var tests = PullRequestSimulations.PullRequest.LoadTests(_testDataFile);
22 |
23 | foreach (var item in tests.Where(t => t.Name.Equals(_testId, StringComparison.InvariantCultureIgnoreCase)).First().Items)
24 | {
25 | DiscoveryResult? resultValue = PullRequestProcessor.GenerateItemResult(_rootDir, item.Path);
26 |
27 | if (resultValue != null)
28 | yield return resultValue.Value;
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/whatsnew.Dockerfile:
--------------------------------------------------------------------------------
1 | FROM mcr.microsoft.com/dotnet/sdk:9.0 as build-env
2 | # Copy everything and publish the release (publish implicitly restores and builds)
3 | WORKDIR /app
4 | COPY . ./
5 | RUN dotnet publish "WhatsNew.Cli/WhatsNew.Cli.csproj" -c Release -o out --no-self-contained
6 |
7 | # Relayer the .NET SDK, anew with the build output
8 | FROM mcr.microsoft.com/dotnet/sdk:9.0
9 | COPY --from=build-env /app/out .
10 | ENTRYPOINT [ "dotnet", "/WhatsNew.dll" ]
--------------------------------------------------------------------------------