From 1ab8f13f4c2370c242d8fee3f852027783e44ca6 Mon Sep 17 00:00:00 2001 From: Riccardo De Agostini Date: Thu, 24 Nov 2022 23:49:39 +0100 Subject: [PATCH] Update infrastructure and docs following the org move from Buildvana to Tenacom --- .config/dotnet-tools.json | 18 +- .editorconfig | 14 +- .github/CODEOWNERS | 26 ++ .github/ISSUE_TEMPLATE/01_bug_report.md | 60 --- .../ISSUE_TEMPLATE/02_enhancement_proposal.md | 73 ---- .github/ISSUE_TEMPLATE/03_blank_issue.md | 7 - .github/ISSUE_TEMPLATE/config.yml | 1 - .github/PULL_REQUEST_TEMPLATE.md | 52 --- .github/dependabot.yml | 4 +- .github/labeler.yml | 95 ++--- .github/labels.json | 34 -- .github/release.yml | 17 + .github/workflows/build-test-pack.yml | 40 ++ .github/workflows/codeql-analysis.yml | 55 +++ .github/workflows/continuous-integration.yml | 43 --- .github/workflows/define-labels.yml | 17 - .github/workflows/label-pull-requests.yml | 10 +- .github/workflows/release.yml | 91 +++++ .gitignore | 14 +- Buildvana.Sdk.sln | 13 +- Buildvana.Sdk.sln.DotSettings | 18 +- Common.props | 39 +- Directory.Build.targets | 3 - Directory.Packages.props | 9 +- LICENSE | 4 +- README.md | 123 +++--- THIRD-PARTY-NOTICES | 14 +- VERSION | 1 - build-config.cmd | 8 - build.cake | 263 +++++++++++++ build.cmd | 271 ------------- build/BuildData.cake | 195 ++++++++++ build/DocFx.cake | 124 ++++++ build/THIRD-PARTY-NOTICES | 34 ++ build/changelog.cake | 266 +++++++++++++ build/dotnet.cake | 143 +++++++ build/environment.cake | 28 ++ build/fail.cake | 75 ++++ build/filesystem.cake | 25 ++ build/git.cake | 180 +++++++++ build/github.cake | 151 ++++++++ build/json.cake | 137 +++++++ build/nbgv.cake | 41 ++ build/options.cake | 144 +++++++ build/process.cake | 38 ++ build/public-api.cake | 181 +++++++++ build/setup-teardown.cake | 33 ++ build/versioning.cake | 362 ++++++++++++++++++ build/workspace.cake | 28 ++ global.json | 2 +- graphics/PackageIcon.png | Bin 46869 -> 44901 bytes graphics/README.md | 49 +++ graphics/Readme.png | Bin 0 -> 57355 bytes graphics/Readme.svg | 113 ++++++ graphics/SocialCard.png | Bin 0 -> 89822 bytes graphics/SocialCard.svg | 163 ++++++++ graphics/SquareLogo.svg | 84 ++++ nuget.config | 5 + .../AdditionalAssemblyInfoGenerator.cs | 8 +- .../Internal/AdditionalAssemblyInfoValues.cs | 8 +- ...AnalyzerConfigOptionsProviderExtensions.cs | 8 +- .../Internal/StringBuilderExtensions.cs | 8 +- stylecop.json | 11 +- version.json | 18 + 64 files changed, 3311 insertions(+), 788 deletions(-) create mode 100644 .github/CODEOWNERS delete mode 100644 .github/ISSUE_TEMPLATE/01_bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/02_enhancement_proposal.md delete mode 100644 .github/ISSUE_TEMPLATE/03_blank_issue.md delete mode 100644 .github/ISSUE_TEMPLATE/config.yml delete mode 100644 .github/PULL_REQUEST_TEMPLATE.md delete mode 100644 .github/labels.json create mode 100644 .github/release.yml create mode 100644 .github/workflows/build-test-pack.yml create mode 100644 .github/workflows/codeql-analysis.yml delete mode 100644 .github/workflows/continuous-integration.yml delete mode 100644 .github/workflows/define-labels.yml create mode 100644 .github/workflows/release.yml delete mode 100644 VERSION delete mode 100644 build-config.cmd create mode 100644 build.cake delete mode 100644 build.cmd create mode 100644 build/BuildData.cake create mode 100644 build/DocFx.cake create mode 100644 build/THIRD-PARTY-NOTICES create mode 100644 build/changelog.cake create mode 100644 build/dotnet.cake create mode 100644 build/environment.cake create mode 100644 build/fail.cake create mode 100644 build/filesystem.cake create mode 100644 build/git.cake create mode 100644 build/github.cake create mode 100644 build/json.cake create mode 100644 build/nbgv.cake create mode 100644 build/options.cake create mode 100644 build/process.cake create mode 100644 build/public-api.cake create mode 100644 build/setup-teardown.cake create mode 100644 build/versioning.cake create mode 100644 build/workspace.cake create mode 100644 graphics/README.md create mode 100644 graphics/Readme.png create mode 100644 graphics/Readme.svg create mode 100644 graphics/SocialCard.png create mode 100644 graphics/SocialCard.svg create mode 100644 graphics/SquareLogo.svg create mode 100644 version.json diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 216dd1e..0815dcc 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -2,10 +2,22 @@ "version": 1, "isRoot": true, "tools": { - "jetbrains.resharper.globaltools": { - "version": "2022.2.4", + "cake.tool": { + "version": "2.2.0", "commands": [ - "jb" + "dotnet-cake" + ] + }, + "nbgv": { + "version": "3.5.119", + "commands": [ + "nbgv" + ] + }, + "dotnet-reportgenerator-globaltool": { + "version": "5.1.12", + "commands": [ + "reportgenerator" ] } } diff --git a/.editorconfig b/.editorconfig index 76ade18..234a04e 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,15 +3,16 @@ root = true # Default settings. [*] +charset = utf-8 indent_style = space indent_size = 4 -end_of_line = crlf +end_of_line = lf insert_final_newline = true trim_trailing_whitespace = true # Code files [*.{cs,csx,vb,vbx}] -insert_final_newline = true +end_of_line = crlf charset = utf-8-bom # Xml project files @@ -19,7 +20,7 @@ charset = utf-8-bom indent_size = 2 # Xml config files -[*.{ruleset,config,nuspec,resx,vsixmanifest,vsct}] +[*.{ruleset,config,nuspec,resx,vsixmanifest,vsct,runsettings}] indent_size = 2 # JSON files @@ -32,15 +33,18 @@ indent_size = 2 # Shell scripts [*.sh] -end_of_line = lf indent_size = 2 +# Windows batch files +[*.{bat,cmd}] +end_of_line = crlf + # Markdown files [*.md] -end_of_line = lf indent_size = 2 trim_trailing_whitespace = false # InnoSetup files [*.iss] +end_of_line = crlf indent_size = 2 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..1bea56f --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,26 @@ +# This file specifies users whose review is automatically requested when a PR modifies certain files. +# For more ionformation see: +# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners + +# GitHub and apps configuration files +/.github/ @rdeago +/.all-contributorsrc @rdeago + +# Git configuration files +/.git* @rdeago + +# Build scripts +*.cake @rdeago + +# Licensing +LICENSE @rdeago +THIRD-PARTY-NOTICES @rdeago + +# Solution infrastructure files +Directory.Build.* @rdeago +.editorconfig @rdeago +.globalconfig @rdeago +stylecop.json @rdeago +*.DotSettings @rdeago +NuGet.config @rdeago +version.json @rdeago diff --git a/.github/ISSUE_TEMPLATE/01_bug_report.md b/.github/ISSUE_TEMPLATE/01_bug_report.md deleted file mode 100644 index ed39096..0000000 --- a/.github/ISSUE_TEMPLATE/01_bug_report.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: 'bug' -assignees: '' ---- - - - -## Current version: - -## Description - - - -## Configuration - - - -## Regression? - - - -## Other information - - diff --git a/.github/ISSUE_TEMPLATE/02_enhancement_proposal.md b/.github/ISSUE_TEMPLATE/02_enhancement_proposal.md deleted file mode 100644 index 02f09e5..0000000 --- a/.github/ISSUE_TEMPLATE/02_enhancement_proposal.md +++ /dev/null @@ -1,73 +0,0 @@ ---- -name: Enhancement proposal -about: Propose an improvement or new functionality -title: '' -labels: 'enhancement' -assignees: '' ---- - -## Current version: - -## Background and motivation - - - -## Proposed enhancement - - - -## Implementation proposals - - - -## Usage examples - - - -## Risks - - diff --git a/.github/ISSUE_TEMPLATE/03_blank_issue.md b/.github/ISSUE_TEMPLATE/03_blank_issue.md deleted file mode 100644 index b0c189e..0000000 --- a/.github/ISSUE_TEMPLATE/03_blank_issue.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -name: Blank issue -about: Something that doesn't fit the other categories -title: '' -labels: '' -assignees: '' ---- diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 3ba13e0..0000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1 +0,0 @@ -blank_issues_enabled: false diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index e8229b4..0000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,52 +0,0 @@ -## Types of changes - - - -- [ ] Bugfix -- [ ] Enhancement (new and/or improved behavior) -- [ ] Refactoring (no functional changes) -- [ ] Code style update (no functional changes) -- [ ] Dependencies added, updated, or removed -- [ ] Build related changes -- [ ] Repository infrastructure changes (e.g. changes to issue / PR templates) -- [ ] CI related changes -- [ ] Documentation update -- [ ] Other (please describe below) - -## Proposed changes / fixed issues - - - -Closes # -Partial fix for # - -## Checklist - - - -- [ ] My contribution is my original work -- [ ] My contribution, or part of it, comes from projects with an MIT-compatible license AND I have updated the THIRD-PARTY-NOTICES file accordingly -- [ ] I have added and/or updated related documentation (if applicable) -- [ ] I have updated the "Unreleased changes" section in [CHANGELOG.md](https://github.com/Buildvana/Buildvana.Sdk/blob/main/CHANGELOG.md) according to the modifications I made - -## Other information - - diff --git a/.github/dependabot.yml b/.github/dependabot.yml index e875327..28791ea 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -3,10 +3,10 @@ updates: - package-ecosystem: "github-actions" directory: "/" schedule: { interval: "daily" } - labels: [ "area-deps", "area-ci" ] + labels: [ "area:deps", "area:ci" ] reviewers: [ "rdeago" ] - package-ecosystem: "nuget" directory: "/" schedule: { interval: "daily" } - labels: [ "area-deps" ] + labels: [ "area:deps" ] reviewers: [ "rdeago" ] diff --git a/.github/labeler.yml b/.github/labeler.yml index 0d91778..4cc1242 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,60 +1,39 @@ -area-core: - - "src/Buildvana.Sdk/Sdk/**/*" - -area-assembly_signing: - - "src/Buildvana.Sdk/Modules/AssemblySigning/**/*" - - "src/Buildvana.Sdk/Tasks/AssemblySigning/**/*" - -area-jetbrains_annotations: - - "src/Buildvana.Sdk/Modules/JetBrainsAnnotations/**/*" - - "src/Buildvana.Sdk/Tasks/JetBrainsAnnotations/**/*" - -area-literal_assembly_attributes: - - "src/Buildvana.Sdk/Modules/LiteralAssemblyAttributes/**/*" - - "src/Buildvana.Sdk/Tasks/LiteralAssemblyAttributes/**/*" - -area-nuget_pack: - - "src/Buildvana.Sdk/Modules/NuGetPack/**/*" - - "src/Buildvana.Sdk/Tasks/NuGetPack/**/*" - -area-standard_analyzers: - - "src/Buildvana.Sdk/Modules/StandardAnalyzers/**/*" - - "src/Buildvana.Sdk/Tasks/StandardAnalyzers/**/*" - -area-thisassembly_class: - - "src/Buildvana.Sdk/Modules/ThisAssemblyClass/**/*" - - "src/Buildvana.Sdk/Tasks/ThisAssemblyClass/**/*" - -area-version_file: - - "src/Buildvana.Sdk/Modules/VersionFile/**/*" - - "src/Buildvana.Sdk/Tasks/VersionFile/**/*" - -area-xml_documentation: - - "src/Buildvana.Sdk/Modules/XmlDocumentation/**/*" - - "src/Buildvana.Sdk/Tasks/XmlDocumentation/**/*" - -area-build: - - "**/*.sln" - - "**/*.csproj" - - "**/Common.props" - - "**/Common.targets" - -area-ci: - - ".github/workflows/**/*" - - "lgtm.yml" - -area-deps: - - "**/Directory.Packages.props" +'area:code': + - '*.sln' + - 'src/**/*' + +'area:style': + - '**/.editorconfig' + - '**/.globalconfig' + - '**/stylecop.json' + - '**/*.DotSettings' + +'area:build': + - '**/*.cake' + - 'build/**/*' + +'area:repo': + - '.github/*.yml' + - '.github/**/*.md' + - CODEOWNERS + - '.github/CODEOWNERS' + +'area:ci': + - '.github/workflows/**/*' + - 'lgtm.yml' + +'area:deps': + - '**/Directory.Packages.props' - Directory.Build.props - Directory.Build.targets - - "src/Buildvana.Sdk/Sdk/PackageVersions.props" - -area-docs: - - "docs/**/*" - - "**/LICENSE" - - "**/README.md" - - "**/THIRD-PARTY-NOTICES" - -area-repo: - - ".github/*.yml" - - ".github/**/*.md" + - global.json + - .config/dotnet-tools.json + +'area:docs': + - 'docs/**/*' + - '.all-contributorsrc' + - '**/CHANGELOG.md' + - '**/LICENSE' + - '**/NuGet-README.md' + - '**/README.md' + - '**/THIRD-PARTY-NOTICES' diff --git a/.github/labels.json b/.github/labels.json deleted file mode 100644 index f27aaba..0000000 --- a/.github/labels.json +++ /dev/null @@ -1,34 +0,0 @@ -[ - { "name": "v1.x", "color": "9c3", "description": "[issue/PR] affects version 1." }, - - { "name": "area-core", "color": "ccc", "description": "[issue/PR] affects SDK core files." }, - { "name": "area-assembly_signing", "color": "ccc", "description": "[issue/PR] affects the AssemblySigning module." }, - { "name": "area-jetbrains_annotations", "color": "ccc", "description": "[issue/PR] affects the JetBrainsAnnotations module." }, - { "name": "area-literal_assembly_attributes", "color": "ccc", "description": "[issue/PR] affects the LiteralAssemblyAttributes module." }, - { "name": "area-nuget_pack", "color": "ccc", "description": "[issue/PR] affects the NuGetPack module." }, - { "name": "area-standard_analyzers", "color": "ccc", "description": "[issue/PR] affects the StandardAnalyzers module." }, - { "name": "area-thisassembly_class", "color": "ccc", "description": "[issue/PR] affects the ThisAssemblyClass module." }, - { "name": "area-version_file", "color": "ccc", "description": "[issue/PR] affects the VersionFile module." }, - { "name": "area-xml_documentation", "color": "ccc", "description": "[issue/PR] affects the XmlDocumentation module." }, - - { "name": "area-build", "color": "ccc", "description": "[issue/PR] affects project files and/or build settings." }, - { "name": "area-repo", "color": "ccc", "description": "[issue/PR] affects repository settings, e.g. issue templates." }, - { "name": "area-deps", "color": "ccc", "description": "[issue/PR] adds, updates, or removes dependencies." }, - { "name": "area-docs", "color": "ccc", "description": "[issue/PR] affects documentation." }, - { "name": "area-ci", "color": "ccc", "description": "[issue/PR] affects CI / CD / actions." }, - - { "name": "bug", "color": "c00", "description": "[issue/PR] raises / solves a bug." }, - { "name": "enhancement", "color": "36c", "description": "[issue/PR] requests / implements new or improved functionality." }, - { "name": "refactor", "color": "069", "description": "[issue/PR] requests / implements a refactor of existing code without affecting functionality." }, - { "name": "style", "color": "cfc", "description": "[PR] contains code style changes." }, - { "name": "design", "color": "cfc", "description": "[issue] Design discussion." }, - - { "name": "breaking", "color": "fc0", "description": "[issue/PR] requires / contains breaking changes." }, - { "name": "help_wanted", "color": "c36", "description": "[issue/PR] needs help to solve / finalize." }, - { "name": "easy", "color": "ccf", "description": "[issue] Easy issue, good pick for new collaborators." }, - - { "name": "invalid", "color": "666", "description": "[issue] Problem caused by user or third-party code, or otherwise not a valid issue." }, - { "name": "duplicate", "color": "666", "description": "[issue] Duplicate of another issue." }, - { "name": "by_design", "color": "666", "description": "[issue] The lamented behavior is by design." }, - { "name": "wontfix", "color": "666", "description": "[issue] Valid issue, but will not be acted upon (see comments)." } -] \ No newline at end of file diff --git a/.github/release.yml b/.github/release.yml new file mode 100644 index 0000000..1f893db --- /dev/null +++ b/.github/release.yml @@ -0,0 +1,17 @@ +changelog: + exclude: + labels: + - ignore-for-release + categories: + - title: Breaking changes + labels: + - breaking + - title: New features + labels: + - enhancement + - title: Bugs fixed + labels: + - bug + - title: Other changes + labels: + - "*" diff --git a/.github/workflows/build-test-pack.yml b/.github/workflows/build-test-pack.yml new file mode 100644 index 0000000..4925452 --- /dev/null +++ b/.github/workflows/build-test-pack.yml @@ -0,0 +1,40 @@ +name: Build, test, and pack + +on: + push: + branches: [ main, 'v[0-9]+.[0-9]+' ] + pull_request: + branches: [ main, 'v[0-9]+.[0-9]+' ] + +jobs: + build_test_pack: + runs-on: windows-latest + env: + DOTNET_NOLOGO: 'true' + DOTNET_CLI_TELEMETRY_OPTOUT: 'true' + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' + DOTNET_CLI_UI_LANGUAGE: 'en-US' + steps: + - name: Checkout repository with full history + uses: actions/checkout@v3 + with: + fetch-depth: 0 # Checkout with full history so nbgv can compute Git height correctly. + - name: Setup .NET SDK + uses: actions/setup-dotnet@v3 + with: + global-json-file: global.json + - name: Restore .NET tools + shell: cmd + run: dotnet tool restore + - name: Run build script + shell: cmd + run: | + if [%CAKE_VERBOSITY%]==[] set CAKE_VERBOSITY=Normal + if [%RUNNER_DEBUG%]==[1] set CAKE_VERBOSITY=Diagnostic + dotnet cake --target Pack --verbosity %CAKE_VERBOSITY% + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + working-directory: ./TestResults/ + files: Cobertura.xml + verbose: true diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..07715b2 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,55 @@ +name: "CodeQL" + +on: + push: + branches: [ main, 'v[0-9]+.[0-9]+' ] + pull_request: + branches: [ main, 'v[0-9]+.[0-9]+' ] + schedule: + - cron: '38 16 * * 6' # At 4:38PM, every Saturday + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + env: + DOTNET_NOLOGO: 'true' + DOTNET_CLI_TELEMETRY_OPTOUT: 'true' + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' + DOTNET_CLI_UI_LANGUAGE: 'en-US' + permissions: + actions: read + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + language: [ 'csharp' ] # https://aka.ms/codeql-docs/language-support + steps: + - name: Checkout repository with full history + uses: actions/checkout@v3 + with: + fetch-depth: 0 # Checkout with full history so nbgv can compute Git height correctly. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + queries: security-and-quality + - name: Setup .NET SDK + uses: actions/setup-dotnet@v3 + with: + global-json-file: global.json + - name: Restore .NET tools + run: dotnet tool restore + - name: Build solution + run: | + if test "$RUNNER_DEBUG" == "1"; then + CAKE_VERBOSITY="Diagnostic" + elif test -z "$CAKE_VERBOSITY"; then + CAKE_VERBOSITY="Normal" + fi + dotnet cake --target Build --verbosity $CAKE_VERBOSITY + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/continuous-integration.yml b/.github/workflows/continuous-integration.yml deleted file mode 100644 index 1cc3257..0000000 --- a/.github/workflows/continuous-integration.yml +++ /dev/null @@ -1,43 +0,0 @@ -name: Continuous integration - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -env: - ContinuousIntegrationBuild: "true" - DOTNET_NOLOGO: "true" - DOTNET_CLI_UI_LANGUAGE: "en-US" - -jobs: - - build: - name: Build and pack on CI server - strategy: - fail-fast: false - matrix: - os: [ ubuntu-latest, windows-latest ] - runs-on: ${{ matrix.os }} - steps: - - - name: Checkout - uses: actions/checkout@v3 - - - name: Setup .NET SDK - uses: actions/setup-dotnet@v3 - with: - global-json-file: global.json - - - name: Restore dependencies - run: dotnet restore - - - name: Build solution - run: dotnet build -c Release --no-restore /maxCpuCount:1 - - - name: Run unit tests - run: dotnet test -c Release --no-build - - - name: Prepare for distribution - run: dotnet pack -c Release --no-build /maxCpuCount:1 diff --git a/.github/workflows/define-labels.yml b/.github/workflows/define-labels.yml deleted file mode 100644 index c2c5a8c..0000000 --- a/.github/workflows/define-labels.yml +++ /dev/null @@ -1,17 +0,0 @@ -name: Define issue labels -on: issues - -jobs: - - labels: - - runs-on: ubuntu-latest - steps: - - - name: Checkout - uses: actions/checkout@v3 - - - name: Update repository labels - uses: lannonbr/issue-label-manager-action@3.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/label-pull-requests.yml b/.github/workflows/label-pull-requests.yml index 4dbb294..d33c312 100644 --- a/.github/workflows/label-pull-requests.yml +++ b/.github/workflows/label-pull-requests.yml @@ -7,16 +7,12 @@ jobs: set_labels: runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write steps: - - name: Checkout uses: actions/checkout@v3 - - - name: Update repository labels - uses: lannonbr/issue-label-manager-action@3.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Assign labels to pull request uses: actions/labeler@v4 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..a7717f1 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,91 @@ +name: Publish a release + +concurrency: + group: release-${{ github.ref }} + cancel-in-progress: true + +on: + workflow_dispatch: + inputs: + versionSpecChange: + description: 'Version spec change' + required: true + type: choice + default: 'None' + options: + - None + - Unstable + - Stable + - Minor + - Major + checkPublicApi: + description: 'Check public API' + required: false + default: true + type: boolean + checkChangelog: + description: 'Check changelog' + required: false + default: true + type: boolean + cakeVerbosity: + description: 'Cake verbosity' + required: true + type: choice + default: 'Normal' + options: + - Normal + - Verbose + - Diagnostic +jobs: + release: + runs-on: windows-latest + env: + DOTNET_NOLOGO: 'true' + DOTNET_CLI_TELEMETRY_OPTOUT: 'true' + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' + DOTNET_CLI_UI_LANGUAGE: 'en-US' + GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} + PRERELEASE_NUGET_SOURCE: 'https://www.myget.org/F/tenacom-preview/api/v3/index.json' + PRERELEASE_NUGET_KEY: ${{ secrets.MYGET_DEPLOYMENT_KEY }} + RELEASE_NUGET_SOURCE: 'https://api.nuget.org/v3/index.json' + RELEASE_NUGET_KEY: ${{ secrets.NUGET_DEPLOYMENT_KEY }} + VERSION_SPEC_CHANGE: ${{ inputs.versionSpecChange }} + CHECK_PUBLIC_API: ${{ inputs.checkPublicApi }} + CHECK_CHANGELOG: ${{ inputs.checkChangelog }} + CAKE_VERBOSITY: ${{ inputs.cakeVerbosity }} + steps: + - name: Log workflow inputs + shell: cmd + run: | + echo Version spec change : %VERSION_SPEC_CHANGE% + echo Check public API : %CHECK_PUBLIC_API% + echo Check changelog : %CHECK_CHANGELOG% + echo Cake verbosity : %CAKE_VERBOSITY% + - name: Checkout repository with full history + uses: actions/checkout@v3 + with: + fetch-depth: 0 # Checkout with full history so nbgv can compute Git height correctly. + token: ${{ secrets.RELEASE_TOKEN }} + persist-credentials: true # We need auth set up in the Cake script + - name: Setup .NET SDK + uses: actions/setup-dotnet@v3 + with: + global-json-file: global.json + - name: Restore .NET tools + shell: cmd + run: dotnet tool restore + - name: Run build script + id: build + shell: cmd + run: | + if [%CAKE_VERBOSITY%]==[] set CAKE_VERBOSITY=Normal + if [%RUNNER_DEBUG%]==[1] set CAKE_VERBOSITY=Diagnostic + dotnet cake --target Release --verbosity %CAKE_VERBOSITY% + - name: Upload coverage to Codecov + uses: codecov/codecov-action@v3 + with: + working-directory: ./TestResults/ + files: Cobertura.xml + name: v${{ steps.build.outputs.version }} + verbose: true diff --git a/.gitignore b/.gitignore index e1a82c6..530fbbf 100644 --- a/.gitignore +++ b/.gitignore @@ -4,8 +4,11 @@ artifacts/ # Local build logs logs/ -# Folders created by CI -.coverage/ +# Cake build +tools/ + +# Testing +TestResults/ # Visual Studio **/bin/ @@ -20,3 +23,10 @@ _ReSharper.*/ # Windows thumbnails Thumbs.db + +# DocFx +docs/globalMetadata.json +docs/api/.manifest +docs/api/*.yml +docs/obj/ +docs/_site/ diff --git a/Buildvana.Sdk.sln b/Buildvana.Sdk.sln index a2da57e..0676992 100644 --- a/Buildvana.Sdk.sln +++ b/Buildvana.Sdk.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.0.32014.148 +VisualStudioVersion = 17.4.33103.184 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Buildvana.Sdk", "src\Buildvana.Sdk\Buildvana.Sdk.csproj", "{3D872329-6B84-4739-B727-1AED462DFD5A}" EndProject @@ -14,11 +14,16 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "- Configuration", "- Config Common.props = Common.props Directory.Build.props = Directory.Build.props Directory.Build.targets = Directory.Build.targets + NuGet.config = NuGet.config + stylecop.json = stylecop.json + version.json = version.json + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "- Dependencies", "- Dependencies", "{C06EF000-C1AC-4661-B818-4795D37C5E8D}" + ProjectSection(SolutionItems) = preProject Directory.Packages.props = Directory.Packages.props + .config\dotnet-tools.json = .config\dotnet-tools.json global.json = global.json - nuget.config = nuget.config - stylecop.json = stylecop.json - VERSION = VERSION EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "- Documentation", "- Documentation", "{F2FA2D74-645C-4F7A-A60D-EE2355E5CBA1}" diff --git a/Buildvana.Sdk.sln.DotSettings b/Buildvana.Sdk.sln.DotSettings index 0a8332b..bbe708e 100644 --- a/Buildvana.Sdk.sln.DotSettings +++ b/Buildvana.Sdk.sln.DotSettings @@ -1,7 +1,6 @@  None NotCompiledCode - True DoShow DoShow @@ -426,14 +425,9 @@ WARNING Experimental True - - - True False - True - - - + False + OPTIMAL_FILL True END_OF_LINE 1 @@ -449,10 +443,10 @@ 0 False True - True - True + True NEVER NEVER + True False NEVER False @@ -490,7 +484,6 @@ System.CodeDom.Compiler.GeneratedCodeAttribute <data><AttributeFilter ClassMask="System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute" IsEnabled="True" /><AttributeFilter ClassMask="System.CodeDom.Compiler.GeneratedCodeAttribute" IsEnabled="True" /></data> True - True True True @@ -498,6 +491,7 @@ True True True + True True True - + diff --git a/Common.props b/Common.props index b410e05..5ce72a2 100644 --- a/Common.props +++ b/Common.props @@ -1,43 +1,48 @@ - - + Buildvana.Sdk - Riccardo De Agostini and Buildvana contributors - Buildvana - The Buildvana team - Copyright (C) 2020-2022 Riccardo De Agostini and Buildvana contributors. + Tenacom and contributors + Tenacom + Tenacom + Copyright (c) $(Authors) + false + https://github.com/Tenacom/Buildvana.Sdk + See $(PackageProjectUrl)/blob/main/CHANGELOG.md + https://github.com/Tenacom/Buildvana.Sdk + true + true + true + true - - true latest + false + true enable true true true - true true false + true + false - + + + + + false - false false false - - - - true - - diff --git a/Directory.Build.targets b/Directory.Build.targets index 98af971..a3481a2 100644 --- a/Directory.Build.targets +++ b/Directory.Build.targets @@ -1,7 +1,4 @@  - - - diff --git a/Directory.Packages.props b/Directory.Packages.props index aac7f59..231b74e 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -10,26 +10,27 @@ The minimum supported version of Roslyn. Used by the SDK to determine whether the compiler in use is supported. --> - 4.3 + 4.4 - .NET SDK v6.0.400+ / Visual Studio 2022 17.3+ + .NET SDK v7.0.100+ / Visual Studio 2022 17.4+ - roslyn4.3 + roslyn4.4 - + + diff --git a/LICENSE b/LICENSE index c482c82..eb57cc5 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ -MIT License +The MIT License (MIT) -Copyright (C) Riccardo De Agostini and Buildvana contributors. All rights reserved. +Copyright (c) Tenacom and contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index c5bf510..ae97548 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,32 @@ -# Buildvana SDK +# ![Buildvana SDK](graphics/Readme.png) -Part of [the Buildvana project](https://github.com/Buildvana/Buildvana). +[![License](https://badgen.net/badge/license/MIT/blue)](https://github.com/Tenacom/Buildvana.Sdk/blob/main/LICENSE) +[![Latest release](https://badgen.net/github/release/Tenacom/Buildvana.Sdk?label=latest)](https://github.com/Tenacom/Buildvana.Sdk/releases) +[![Latest stable release](https://badgen.net/github/release/Tenacom/Buildvana.Sdk/stable?label=stable)](https://github.com/Tenacom/Buildvana.Sdk/releases) +[![Changelog](https://badgen.net/badge/changelog/Keep%20a%20Changelog%20v1.0.0/orange)](https://github.com/Tenacom/Buildvana.Sdk/blob/main/CHANGELOG.md) -[![License](https://img.shields.io/github/license/Buildvana/Buildvana.Sdk.svg)](https://github.com/Buildvana/Buildvana.Sdk/blob/main/LICENSE) -[![GitHub release (latest by date including pre-releases)](https://img.shields.io/github/v/release/Buildvana/Buildvana.Sdk?include_prereleases)](https://github.com/Buildvana/Buildvana.Sdk/releases) -[![Changelog](https://img.shields.io/badge/changelog-Keep%20a%20Changelog%20v1.0.0-%23E05735)](https://github.com/Buildvana/Buildvana.Sdk/blob/main/CHANGELOG.md) +[![Build, test, and pack](https://github.com/Tenacom/Buildvana.Sdk/actions/workflows/build-test-pack.yml/badge.svg)](https://github.com/Tenacom/Buildvana.Sdk/actions/workflows/build-test-pack.yml) +[![CodeQL](https://github.com/Tenacom/Buildvana.Sdk/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/Tenacom/Buildvana.Sdk/actions/workflows/codeql-analysis.yml) -[![CodeFactor](https://www.codefactor.io/repository/github/buildvana/buildvana.sdk/badge)](https://www.codefactor.io/repository/github/buildvana/buildvana.sdk) -[![Last commit](https://img.shields.io/github/last-commit/Buildvana/Buildvana.Sdk.svg)](https://github.com/Buildvana/Buildvana.Sdk/commits/main) -[![Open issues](https://img.shields.io/github/issues-raw/Buildvana/Buildvana.Sdk.svg?label=open+issues)](https://github.com/Buildvana/Buildvana.Sdk/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) -[![Closed issues](https://img.shields.io/github/issues-closed-raw/Buildvana/Buildvana.Sdk.svg?label=closed+issues)](https://github.com/Buildvana/Buildvana.Sdk/issues?q=is%3Aissue+is%3Aclosed+sort%3Aupdated-desc) +![Repobeats analytics image](https://repobeats.axiom.co/api/embed/733fff6e0c96c981b6229b450fdf4df3e1b4e584.svg "Repobeats analytics image") -[![Slack](https://img.shields.io/badge/join_us-on_Slack-ff7fc0.svg?logo=slack)](https://join.slack.com/t/buildvana/shared_invite/zt-e667rvy8-hCtADFiuF8OuiYvthIiWVw) +| Latest packages | NuGet | MyGet | +|-----------------|-------|-------| +| Buildvana.Sdk | [![Buildvana.Sdk @ NuGet](https://badgen.net/nuget/v/Buildvana.Sdk?icon=nuget&label=)](https://nuget.org/packages/Buildvana.Sdk) | [![Buildvana.Sdk @ MyGet](https://img.shields.io/myget/tenacom-preview/vpre/Buildvana.Sdk?label=&color=orange)](https://www.myget.org/feed/tenacom-preview/package/nuget/Buildvana.Sdk) | --- - [At a glance](#at-a-glance) - [Benefits](#benefits) - - [Supported project types](#supported-project-types) - - [Requirements](#requirements) - - [Git repository](#git-repository) + - [Compatibility](#compatibility) + - [Project types](#project-types) + - [Programming languages](#programming-languages) + - [Git servers](#git-servers) - [Toolchain](#toolchain) - [Quick start](#quick-start) - [Contributing](#contributing) -- [Credits](#credits) - ---- - -![Buildvana SDK](https://raw.githubusercontent.com/Buildvana/Buildvana/main/graphics/Buildvana-Readme.png) - -**Buildvana** _/bɪldˈvɑːnə/_ - -1. a transcendent state of the .NET programmer's mind, in which there is neither suffering, confusion, nor waste of time. - -2. a collection of open-source methods and processes to help .NET programmers achieve Buildvana. - -3. a collection of open-source projects supporting programmers that aim to reach Buildvana. +- [Contributors](#contributors) +- [Proudly built using Buildvana SDK](#proudly-built-using-buildvana-sdk) --- @@ -43,61 +34,53 @@ Part of [the Buildvana project](https://github.com/Buildvana/Buildvana). Buildvana SDK is an opinionated, best-practices-based, CI-friendly, VS-friendly, MSBuild-powered build system for .NET projects. -It is part of [the Buildvana project](https://github.com/Buildvana/), which also comprises ready-to-use template repositories that implement automated build, testing, and deployment for .NET projects. - -> **DISCLAIMER:** Buildvana SDK, just as the whole Buildvana project, is still a work in progress. +> **DISCLAIMER:** Buildvana SDK is still a work in progress. Your mileage may vary, if you break your build you own both pieces, and so on and so forth. However, Buildvana SDK has already been used successfully in production, for both business and open source projects. ### Benefits -- Single source of truth for assembly versions -- Single source of truth for package licenses and copyright notices - Helps you keep your project files clean and concise - even better than "plain" MSBuild SDKs +- Single source of truth for assembly versions (via [`Nerdbank.GitVersioning`(https://github.com/dotnet/Nerdbank.GitVersioning)]) +- Single source of truth for package licenses and copyright notices - More auto-generated assembly information (`ClsCompliant`, `COMVisible`) -- Custom auto-generated assembly information - Automatic configuration of commonly-used code analyzers - ... -### Supported project types +### Compatibility + +#### Project types - :heart: Multi-platform / Cross-platform projects - :heart: Libraries - :heart: Console apps - :heart: Windows Forms - :heart: Projects using `Microsoft.Build.NoTargets` SDK -- :heart: [Avalonia](https://avaloniaui.net) (still experimenting, but no problems so far) +- :heart: [Avalonia UI](https://avaloniaui.net) (still experimenting, but no problems so far) - :question: WPF (testers welcome) - :question: [UNO Platform](https://platform.uno) (testers welcome) +- :question: MAUI (testers welcome) - :question: All kinds of Web projects (testers welcome) - :thumbsdown: Legacy (non-SDK) projects -### Supported languages +#### Programming languages - :heart: C# - :heart: Visual Basic - :yellow_heart: F# (some features disabled) - :thumbsdown: other languages -### Requirements - -#### Git repository - -Buildvana SDK assumes that your project is in a Git repository. Furthermore, if your project is packable (i.e. it is meant to be distributed as a NuGet package), Buildvana SDK assumes that it is hosted on a GitHub public repository, for the purposes of generating a symbol package with SourceLink support. +#### Git servers -Support for other Git servers will be implemented if / when asked for. It should be trivial enough, as long as there is a suitable SourceLink support package available. - -Private repositories may or may not work. Testers welcome. +- :heart: GitHub / GitHub Enterprise +- :yellow_heart: All others (no automatic SourceLink configuration) #### Toolchain -Building via the following tools is supported: - -- MSBuild v17.0 or newer (`msbuild`) running under .NET Framework 4.7.2 or newer / .NET 6.0 or newer -- Visual Studio 2022 v17.0 or newer (building from IDE) -- .NET SDK 6.0 or newer (`dotnet build`, `dotnet msbuild`, etc.) - -Latest versions of Visual Studio for Mac _should_ work, but we need confirmation by someone with a Mac. +- :heart: MSBuild v17.4 or newer (`msbuild`) running under .NET Framework 4.7.2 or newer / .NET 7.0 or newer +- :heart: Visual Studio 2022 v17.4 or newer (building from IDE) +- :heart: .NET SDK 7.0.100 or newer (`dotnet build`, `dotnet msbuild`, etc.) +- :question: Visual Studio for Mac (_should_ work, but we need confirmation by someone with a Mac) ## Quick start @@ -105,17 +88,39 @@ Latest versions of Visual Studio for Mac _should_ work, but we need confirmation ## Contributing -**TODO** +_Of course_ we accept contributions! :smiley: Just take a look at our [Code of Conduct](https://github.com/Tenacom/.github/blob/main/CODE_OF_CONDUCT.md) and [Contributors guide](https://github.com/Tenacom/.github/blob/main/CONTRIBUTING.md), create your fork, and let's party! :tada: + +## Contributors + + + + + + + + + + + + + + + +

Riccardo De Agostini
+ + Add your contributions + +
+ + + + + ## Proudly built using Buildvana SDK -- [PolyKit](https://github.com/Buildvana/PolyKit), itself a part of the Buildvana project, is both a polyfill library _and_ a polyfill construction kit for C# projects. -- [L.o.U.I.S.](https://github.com/Tenacom/Louis) is a general-purpose library, providing both polyfills (via PolyKit) and commonly-used types, suitable for multi-platform libraries and applications. +- [PolyKit](https://github.com/Buildvana/PolyKit) is the last polyfill library you'll ever need for your C# projects. +- [L.o.U.I.S.](https://github.com/Tenacom/Louis) is a general-purpose library, providing commonly-used types, suitable for multi-platform libraries and applications. - [Cecil.XmlDocNames](https://github.com/Tenacom/Cecil.XmlDocNames) is a tiny library that generates XML-documentation-compliant names for [Mono.Cecil](https://github.com/jbevain/cecil) objects. - [ReSharper.ExportAnnotations](https://github.com/Tenacom/ReSharper.ExportAnnotations) lets you distribute ReSharper code annotations in XML format along with your libraries, without keeping a transient dependency on the [JetBrains.Annotations](https://www.nuget.org/packages/JetBrains.Annotations) package. -- Practically every one of [Tenacom](https://github.com/Tenacom)'s private projects since the first preview of Buildvana SDK: almost 50 libraries, a bunch of console apps, some WinForms apps, even an Avalonia app (with more coming soon). -## Credits - -The peaceful octopus logo is a modified version of [Peace](https://thenounproject.com/icon/1951204) by AomAm from [the Noun Project](https://thenounproject.com/). - -The font used in the logo is [Repo](https://fontlibrary.org/en/font/repo) by Stefan Peev, from [Font Library](https://fontlibrary.org). +- Practically every one of [Tenacom](https://github.com/Tenacom)'s private projects since the first preview of Buildvana SDK: almost 50 libraries, a bunch of console apps, some WinForms apps, even an Avalonia UI app (with more coming soon). diff --git a/THIRD-PARTY-NOTICES b/THIRD-PARTY-NOTICES index 396ecdb..3c498d0 100644 --- a/THIRD-PARTY-NOTICES +++ b/THIRD-PARTY-NOTICES @@ -1,15 +1,17 @@ -Buildvana SDK uses third-party material as listed below. -The attached notices are provided for informational purposes only. - -This project uses and/or incorporates third-party libraries or other resources +This project may use and/or incorporate third-party libraries or other resources that may be distributed under licenses different than this project. In the event that we accidentally failed to list a required notice, please bring it to our attention. Either post an issue, or email us: - info@buildvana.net + info@tenacom.it + +The attached notices are provided for information only. -The attached notices are provided for informational purposes only. +================================================================================================ +Third-party graphic elements (fonts, icons, etc.) +------------------------------------------------------------------------------------------------ +Third-party copyright notices for graphic elements are in graphics/README.md ================================================================================================ Nerdbank.MSBuildExtension - https://github.com/AArnott/Nerdbank.MSBuildExtension diff --git a/VERSION b/VERSION deleted file mode 100644 index 3cf286c..0000000 --- a/VERSION +++ /dev/null @@ -1 +0,0 @@ -1.0.0-alpha.23 diff --git a/build-config.cmd b/build-config.cmd deleted file mode 100644 index 5dc844c..0000000 --- a/build-config.cmd +++ /dev/null @@ -1,8 +0,0 @@ -set _SOLUTION_NAME= -set _DEFAULT_TASK= -set _MSBUILD_CONFIGURATION=Release -set _MSBUILD_VERBOSITY=normal -set _MSBUILD_OPTIONS= -set _SKIP_INSPECT=0 -set _SKIP_TEST=0 -set _SKIP_PUSH=1 diff --git a/build.cake b/build.cake new file mode 100644 index 0000000..295ae27 --- /dev/null +++ b/build.cake @@ -0,0 +1,263 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#load "./build/BuildData.cake" +#load "./build/changelog.cake" +#load "./build/dotnet.cake" +#load "./build/environment.cake" +#load "./build/fail.cake" +#load "./build/filesystem.cake" +#load "./build/git.cake" +#load "./build/github.cake" +#load "./build/json.cake" +#load "./build/nbgv.cake" +#load "./build/options.cake" +#load "./build/process.cake" +#load "./build/public-api.cake" +#load "./build/setup-teardown.cake" +#load "./build/versioning.cake" +#load "./build/workspace.cake" + +#nullable enable + +using System; +using System.Text; + +using SysFile = System.IO.File; +using SysPath = System.IO.Path; + +// ============================================================================================= +// TASKS +// ============================================================================================= + +Task("Default") + .Description("Default task - Do nothing (but log build configuration data)") + .Does(context => { + context.Information("The default task does nothing. This is intentional."); + context.Information("Use `dotnet cake --description` to see the list of available tasks."); + }); + +Task("CleanAll") + .Description("Delete all output directories, VS data, R# caches") + .Does((context, data) => context.CleanAll(data)); + +Task("LocalCleanAll") + .Description("Like CleanAll, but only runs on a local machine") + .WithCriteria(data => !data.IsCI) + .Does((context, data) => context.CleanAll(data)); + +Task("Restore") + .Description("Restores dependencies") + .IsDependentOn("LocalCleanAll") + .Does((context, data) => context.RestoreSolution(data)); + +Task("Build") + .Description("Build all projects") + .IsDependentOn("Restore") + .Does((context, data) => context.BuildSolution(data, false)); + +Task("Test") + .Description("Build all projects and run tests") + .IsDependentOn("Build") + .Does((context, data) => context.TestSolution(data, false, false, true)); + +Task("Pack") + .Description("Build all projects, run tests, and prepare build artifacts") + .IsDependentOn("Test") + .Does((context, data) => context.PackSolution(data, false, false)); + +Task("Release") + .Description("Publish a new public release (CI only)") + .Does(async (context, data) => { + + // Perform some preliminary checks + Ensure(data.IsCI, "The Release target cannot run on a local system."); + Ensure(data.IsPublicRelease, "Cannot create a release from the current branch."); + + // Compute the version spec change to apply, if any + // This implies more checks and possibly throws, so do it as early as possible + var versionSpecChange = context.ComputeVersionSpecChange( + currentVersion: data.Version, + requestedChange: context.GetOption("versionSpecChange", VersionSpecChange.None), + checkPublicApi: context.GetOption("checkPublicApi", true)); + + // Identify Git user for later push if needed + context.GitSetUserIdentity("Buildvana", "buildvana@tenacom.it"); + + // Create the release as a draft first, so if the token has no permissions we can bail out early + var releaseId = await context.CreateDraftReleaseAsync(data); + var dupeTagChecked = false; + var committed = false; + try + { + // Modify version if required. + if (versionSpecChange != VersionSpecChange.None) + { + var versionFile = VersionFile.Load(); + if (versionFile.ApplyVersionSpecChange(context, versionSpecChange)) + { + versionFile.Save(); + UpdateRepo(versionFile.Path); + } + } + + // Update public API files only when releasing a stable version + if (!data.IsPrerelease) + { + var modified = context.TransferAllPublicApiToShipped().ToArray(); + if (modified.Length > 0) + { + context.Information($"{modified.Length} public API files were modified."); + UpdateRepo(modified); + } + else + { + context.Information("No public API files were modified."); + } + } + else + { + context.Information("Public API update skipped: not needed on prerelease."); + } + + // Update changelog only on non-prerelease + if (!data.IsPrerelease) + { + if (context.GetOption("checkChangelog", true)) + { + Ensure( + context.ChangelogHasUnreleasedChanges(data.ChangelogPath), + $"Changelog check failed: the \"Unreleased changes\" section is empty or only contains sub-section headings."); + + context.Information($"Changelog check successful: the \"Unreleased changes\" section is not empty."); + } + else + { + context.Information($"Changelog check skipped: option 'checkChangelog' is false."); + } + + // Update the changelog and commit the change before building. + // This ensures that the Git height is up to date when computing a version for the build artifacts. + context.PrepareChangelogForRelease(data); + UpdateRepo(data.ChangelogPath); + } + else + { + context.Information("Changelog update skipped: not needed on prerelease."); + } + + // Ensure that the release tag doesn't already exist. + // This assumes that full repo history has been checked out; + // however, that is already a prerequisite for using Nerdbank.GitVersioning. + Ensure(!context.GitTagExists(data.VersionStr), $"Tag {data.VersionStr} already exists in repository."); + dupeTagChecked = true; + + context.RestoreSolution(data); + context.BuildSolution(data, false); + context.TestSolution(data, false, false, false); + context.PackSolution(data, false, false); + + if (!data.IsPrerelease) + { + // Change the new section's title in the changelog to reflect the actual version. + context.UpdateChangelogNewSectionTitle(data); + UpdateRepo(data.ChangelogPath); + } + else + { + context.Information("Changelog section title update skipped: not needed on prerelease."); + } + + if (committed) + { + context.Information($"Git pushing changes to {data.Remote}..."); + _ = context.Exec("git", $"push {data.Remote} HEAD"); + } + else + { + context.Information("Git push skipped: no commit to push."); + } + + // Publish NuGet packages + context.NuGetPushAll(data); + + // If this is not a prerelease and we are releasing from the main branch, + // dispatch a separate workflow to publish documentation. + // Unless, of course, there is no documentation workflow. + FilePath pagesDeploymentWorkflow = ".github/workflows/deploy-pages.yml"; + if (!SysFile.Exists(pagesDeploymentWorkflow.FullPath)) + { + context.Information($"Documentation update skipped: there is no documentation workflow."); + } + else if (data.IsPrerelease) + { + context.Information("Documentation update skipped: not needed on prerelease."); + } + else if (data.Branch != "main") + { + context.Information($"Documentation update skipped: releasing from '{data.Branch}', not 'main'."); + } + else + { + await context.DispatchWorkflow(data, SysPath.GetFileName(pagesDeploymentWorkflow.FullPath), "main"); + } + + // Last but not least, publish the release. + await context.PublishReleaseAsync(data, releaseId); + + // Set outputs for subsequent steps in GitHub Actions + if (data.IsGitHubAction) + { + context.SetActionsStepOutput("version", data.VersionStr); + } + } + catch (Exception e) + { + context.Error(e is CakeException ? e.Message : $"{e.GetType().Name}: {e.Message}"); + await context.DeleteReleaseAsync(data, releaseId, dupeTagChecked ? data.VersionStr : null); + throw; + } + + void UpdateRepo(params FilePath[] files) + { + foreach (var path in files) + { + context.Verbose($"Git adding {path}..."); + _ = context.Exec( + "git", + new ProcessArgumentBuilder() + .Append("add") + .AppendQuoted(path.FullPath)); + } + + context.Information(committed ? "Amending commit..." : "Committing changed files..."); + var arguments = new ProcessArgumentBuilder().Append("commit"); + if (committed) + { + arguments = arguments.Append("--amend"); + } + + arguments = arguments.Append("-m").AppendQuoted("Prepare release [skip ci]"); + _ = context.Exec("git", arguments); + + // The commit changed the Git height, so update build data + // and amend the commit adding the right version. + // Amending a commit does not further change the Git height. + data.Update(context); + _ = context.Exec( + "git", + new ProcessArgumentBuilder() + .Append("commit") + .Append("--amend") + .Append("-m") + .AppendQuoted($"Prepare release {data.VersionStr} [skip ci]")); + + committed = true; + } + }); + +// ============================================================================================= +// EXECUTION +// ============================================================================================= + +RunTarget(Argument("target", "Default")); diff --git a/build.cmd b/build.cmd deleted file mode 100644 index 3169a57..0000000 --- a/build.cmd +++ /dev/null @@ -1,271 +0,0 @@ -@echo off & setlocal EnableExtensions EnableDelayedExpansion -pushd "%~dp0" - -:: .NET environment variables -set DOTNET_NOLOGO=true -set DOTNET_CLI_UI_LANGUAGE=en-US - -:: Configuration values -set _ARTIFACTS_DIRECTORY= -set _NUPKG_DIRECTORY= -set _SOLUTION_NAME= -set _DEFAULT_TASK= -set _MSBUILD_CONFIGURATION= -set _MSBUILD_VERBOSITY= -set _MSBUILD_OPTIONS= -set _SKIP_INSPECT= -set _SKIP_TEST= -set _SKIP_PUSH= -set _VS_MSBUILD_EXE= -set _NUGET_PUSH_SOURCE= -set _NUGET_PUSH_API_KEY= -set _NUGET_PUSH_SYMBOL_SOURCE= -set _NUGET_PUSH_SYMBOL_API_KEY= - -:: Load configuration -if exist build-config.cmd call build-config.cmd - -:: Default for solution name is the same name as containing folder, including extension -if "%_SOLUTION_NAME%" == "" call :F_SetToCurrentDirectoryName _SOLUTION_NAME -set _SOLUTION_FILE=%_SOLUTION_NAME%.sln -if not exist "%_SOLUTION_FILE%" ( - echo *** Solution file '%_SOLUTION_FILE%' not found. >CON: - exit /B 1 -) - -:: Other default configuration values -if "%_DEFAULT_TASK%"=="" set _DEFAULT_TASK=Pack -if "%_MSBUILD_CONFIGURATION%"=="" set _MSBUILD_CONFIGURATION=Release -if "%_MSBUILD_VERBOSITY%"=="" set _MSBUILD_VERBOSITY=normal -if "%_MSBUILD_OPTIONS%"=="" set _MSBUILD_OPTIONS= -if "%_SKIP_INSPECT%"=="" set _SKIP_INSPECT=0 -if "%_SKIP_TEST%"=="" set _SKIP_TEST=0 -if "%_SKIP_PUSH%"=="" set _SKIP_PUSH=0 -if "%_VS_MSBUILD_EXE%"=="" set _VS_MSBUILD_EXE="%ProgramFiles%\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" -if "%_NUGET_PUSH_SYMBOL_SOURCE%" == "" set _NUGET_PUSH_SYMBOL_SOURCE=%_NUGET_PUSH_SOURCE% -if "%_NUGET_PUSH_SYMBOL_API_KEY%" == "" set _NUGET_PUSH_SYMBOL_SOURCE=%_NUGET_PUSH_API_KEY% - -:: Default for artifacts directory, as per Buildvana SDK defaults -if "%_ARTIFACTS_DIRECTORY%" == "" set _ARTIFACTS_DIRECTORY=artifacts - -:: Default for NuGet package directory, as per Buildvana SDK defaults -if "%_NUPKG_DIRECTORY%" == "" set _NUPKG_DIRECTORY=%_ARTIFACTS_DIRECTORY%\%_MSBUILD_CONFIGURATION% - -:: Use Visual Studio's MSBuild if specified -if /I "%1" equ "VS" ( - set _VS=1 - shift -) - -:: Task to run -set _TASK=%1 -if "%_TASK%"=="" set _TASK=%_DEFAULT_TASK% - -:: Define task dependencies -if /I "%_TASK%"=="Clean" ( - call :F_Run_Tasks Clean -) else if /I "%_TASK%"=="Tools" ( - call :F_Run_Tasks Clean Tools -) else if /I "%_TASK%"=="Restore" ( - call :F_Run_Tasks Clean Tools Restore -) else if /I "%_TASK%"=="Build" ( - call :F_Run_Tasks Clean Tools Restore Build -) else if /I "%_TASK%"=="Inspect" ( - call :F_Run_Tasks Clean Tools Restore Build Inspect -) else if /I "%_TASK%"=="Test" ( - call :F_Run_Tasks Clean Tools Restore Build Inspect Test -) else if /I "%_TASK%"=="Pack" ( - call :F_Run_Tasks Clean Tools Restore Build Inspect Test Pack -) else if /I "%_TASK%"=="Push" ( - call :F_Run_Tasks Clean Tools Restore Build Inspect Test Pack Push -) else if /I "%_TASK%"=="All" ( - call :F_Run_Tasks Clean Tools Restore Build Inspect Test Pack Push -) else ( - echo *** Unknown task '%_TASK%' -) - -popd -exit /B %ERRORLEVEL% - -:: RUN TASKS - -:F_Run_Tasks -set _LOGS_DIR=logs -mkdir "%~dp0%_LOGS_DIR%" >nul 2>&1 -set _LOGFILE="%~dp0%_LOGS_DIR%\build.log" -if exist %_LOGFILE% del %_LOGFILE% -call :F_Timestamp - -:L_Run_Tasks_Loop -if "%1"=="" exit /B 0 -if "%_VS%" == "" ( call :T_%1 ) else ( call :T_VS_%1 ) -if errorlevel 1 exit /B %ERRORLEVEL% -shift -goto :L_Run_Tasks_Loop - -:: TASKS - -:T_Clean -:T_VS_Clean -call :F_Label Clean output directories -if exist "%~dp0%_ARTIFACTS_DIRECTORY%\" call :F_Exec rmdir /S /Q "%~dp0%_ARTIFACTS_DIRECTORY%" -if exist "%~dp0.vs\" call :F_Exec rmdir /S /Q "%~dp0.vs" -if exist "%~dp0_ReSharper.Caches\" call :F_Exec rmdir /S /Q "%~dp0_ReSharper.Caches" -for /F "tokens=*" %%G in ('dir /B /AD /S bin 2^>nul ^& dir /B /AD /S obj 2^>nul') do call :F_Exec rmdir /S /Q "%%G" -exit /B %ERRORLEVEL% - -:T_Tools -call :F_Label Restore .NET CLI tools -call :F_Exec dotnet tool restore -exit /B %ERRORLEVEL% - -:T_VS_Tools -:: No .NET CLI = no tools to restore -exit /B 0 - -:T_Inspect -if %_SKIP_INSPECT% gtr 0 ( - call :F_Label Skip code inspection ^(disabled in configuration^) - exit /B 0 -) -call :F_Label Inspect code with ReSharper tools -call :F_Exec dotnet jb inspectcode "%_SOLUTION_FILE%" --no-build --output=%_LOGS_DIR%\inspect.log --format=Text -exit /B %ERRORLEVEL% - -:T_VS_Inspect -call :F_Label Skip code inspection ^(always disabled when using Visual Studio's MSBuild^) -exit /B 0 - -:T_Restore -call :F_Label Restore dependencies -call :F_Exec dotnet restore --verbosity %_MSBUILD_VERBOSITY% %_MSBUILD_OPTIONS% -exit /B %ERRORLEVEL% - -:T_VS_Restore -call :F_Label Restore dependencies -call :F_Exec %_VS_MSBUILD_EXE% -t:restore -v:%_MSBUILD_VERBOSITY% %_MSBUILD_OPTIONS% -exit /B %ERRORLEVEL% - -:T_Build -call :F_Label Build solution -call :F_Exec dotnet build -c %_MSBUILD_CONFIGURATION% --verbosity %_MSBUILD_VERBOSITY% --no-restore -maxCpuCount:1 %_MSBUILD_OPTIONS% -exit /B %ERRORLEVEL% - -:T_VS_Build -call :F_Label Build solution -call :F_Exec %_VS_MSBUILD_EXE% -t:build -p:Configuration=%_MSBUILD_CONFIGURATION% -v:%_MSBUILD_VERBOSITY% -restore:False -maxCpuCount:1 %_MSBUILD_OPTIONS% -exit /B %ERRORLEVEL% - -:T_Test -if %_SKIP_TEST% gtr 0 ( - call :F_Label Skip unit tests ^(disabled in configuration^) - exit /B 0 -) -call :F_Label Run unit tests -call :F_Exec dotnet test -c %_MSBUILD_CONFIGURATION% --verbosity %_MSBUILD_VERBOSITY% --no-build %_MSBUILD_OPTIONS% -exit /B %ERRORLEVEL% - -:T_VS_Test -call :F_Label Skipping unit tests ^(always disabled when using Visual Studio's MSBuild^) -exit /B 0 - -:T_Pack -call :F_Label Prepare for distribution -call :F_Exec dotnet pack -c %_MSBUILD_CONFIGURATION% --verbosity %_MSBUILD_VERBOSITY% --no-build -maxCpuCount:1 %_MSBUILD_OPTIONS% -exit /B %ERRORLEVEL% - -:T_VS_Pack -call :F_Label Prepare for distribution -call :F_Exec %_VS_MSBUILD_EXE% -t:pack -p:Configuration=%_MSBUILD_CONFIGURATION% -v:%_MSBUILD_VERBOSITY% -p:NoBuild=true -maxCpuCount:1 %_MSBUILD_OPTIONS% -exit /B %ERRORLEVEL% - -:T_Push -if %_SKIP_PUSH% gtr 0 ( - call :F_Label Skipping NuGet push ^(disabled in configuration^) - exit /B 0 -) -if not exist "%~dp0%_NUPKG_DIRECTORY%\*.nupkg" ( - call :F_Label Skipping NuGet push ^(no packages to push^) - exit /B 0 -) -if "%_NUGET_PUSH_SOURCE%" == "" ( - call :F_Error _NUGET_PUSH_SOURCE not configured! - exit /B 1 -) -if "%_NUGET_PUSH_API_KEY%" == "" ( - call :F_Error _NUGET_PUSH_API_KEY not configured! - exit /B 1 -) -call :F_Label Push packages to NuGet server -call :F_Exec pushd "%~dp0%_NUPKG_DIRECTORY%" -for /F "tokens=*" %%G in ('dir /B *.nupkg') do ( - call :F_Exec dotnet nuget push %%G --source %_NUGET_PUSH_SOURCE% --api-key %_NUGET_PUSH_API_KEY% --symbol-source %_NUGET_PUSH_SYMBOL_SOURCE% --symbol-api-key %_NUGET_PUSH_SYMBOL_API_KEY% - if errorlevel 1 exit /B %ERRORLEVEL% -) -call :F_Exec popd -exit /B 0 - -:T_VS_Push -call :F_Label Skip NuGet push ^(always disabled when using Visual Studio's MSBuild^) -exit /B 0 - -:: SUB-ROUTINES - -:F_CleanDirectory -echo --- rmdir /S /Q %1 >CON: -echo --- rmdir /S /Q %1 >>%_LOGFILE% 2>&1 -rmdir /S /Q %1 >nul 2>&1 -exit /B 0 - -:F_Exec -echo --- %* >CON: -echo --- %* >>%_LOGFILE% 2>&1 -%* >>%_LOGFILE% 2>&1 -set _EL=%ERRORLEVEL% -echo; >>%_LOGFILE% 2>&1 -call :F_Display_Errorlevel %_EL% -exit /B %_EL% - -:F_Timestamp -call :F_Timestamp_Core >CON: -call :F_Timestamp_Core >>%_LOGFILE% 2>&1 -exit /B 0 - -:F_Timestamp_Core -echo; -echo ===^>^>^> '%_SOLUTION_NAME%' %DATE% %TIME% -exit /B 0 - -:F_Label -call :F_Label_Core %* >CON: -call :F_Label_Core %* >>%_LOGFILE% 2>&1 -exit /B 0 - -:F_Label_Core -echo; -echo ^>^>^> %* -exit /B 0 - -:F_Error -call :F_Error_Core %* >CON: -call :F_Error_Core %* >>%_LOGFILE% 2>&1 -exit /B 0 - -:F_Error_Core -echo ^*^*^* %* -exit /B 0 - -:F_Display_Errorlevel -if "%1%"=="0" exit /B 0 -call :F_Error ERRORLEVEL = %1 -exit /B 0 - -:F_SetToCurrentDirectoryName -call :F_SetToCurrentDirectoryName_Core %1 "%CD%" -exit /B 0 - -:F_SetToCurrentDirectoryName_Core -set %1=%~nx2 -exit /B 0 - -:: EOF diff --git a/build/BuildData.cake b/build/BuildData.cake new file mode 100644 index 0000000..14bc2fc --- /dev/null +++ b/build/BuildData.cake @@ -0,0 +1,195 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#nullable enable + +using NuGet.Versioning; + +// --------------------------------------------------------------------------------------------- +// BuildData: a record to hold build configuration data +// --------------------------------------------------------------------------------------------- + +/* + * Summary : Holds configuration data for the build. + */ +sealed class BuildData +{ + /* + * Summary : Initializes a new instance of the BuildData class. + * Params : host - The Cake build script host. + */ + public BuildData(ICakeContext context) + { + Ensure(context.TryGetRepositoryInfo(out var repository), 255, "Cannot determine repository owner and name."); + var changelogPath = new FilePath("CHANGELOG.md"); + var solutionPath = context.GetFiles("*.sln").FirstOrDefault() ?? Fail(255, "Cannot find a solution file."); + var solution = context.ParseSolution(solutionPath); + var configuration = context.Argument("configuration", "Release"); + var artifactsPath = new DirectoryPath("artifacts").Combine(configuration); + var testResultsPath = new DirectoryPath("TestResults"); + var isGitHubAction = context.EnvironmentVariable("GITHUB_ACTIONS", false); + var isCI = isGitHubAction + || context.EnvironmentVariable("CI", false) + || context.EnvironmentVariable("CONTINUOUS_INTEGRATION", false) + || context.EnvironmentVariable("TF_BUILD", false) + || context.EnvironmentVariable("GITLAB_CI", false) + || context.EnvironmentVariable("TRAVIS", false) + || context.EnvironmentVariable("APPVEYOR", false) + || context.EnvironmentVariable("CIRCLECI", false) + || context.HasEnvironmentVariable("TEAMCITY_VERSION") + || context.HasEnvironmentVariable("JENKINS_URL"); + + var (versionStr, @ref, isPublicRelease, isPrerelease) = context.GetVersionInformation(); + var version = SemanticVersion.Parse(versionStr); + var branch = context.GetCurrentGitBranch(); + var msBuildSettings = new DotNetMSBuildSettings { + MaxCpuCount = 1, + ContinuousIntegrationBuild = isCI, + NoLogo = true, + }; + + RepositoryHostUrl = repository.HostUrl; + RepositoryOwner = repository.Owner; + RepositoryName = repository.Name; + Remote = repository.Remote; + Ref = @ref; + Branch = branch; + ArtifactsPath = artifactsPath; + TestResultsPath = testResultsPath; + ChangelogPath = changelogPath; + SolutionPath = solutionPath; + Solution = solution; + Configuration = configuration; + VersionStr = versionStr; + Version = version; + IsPublicRelease = isPublicRelease; + IsPrerelease = isPrerelease; + IsGitHubAction = isGitHubAction; + IsCI = isCI; + MSBuildSettings = msBuildSettings; + + context.Information("Build configuration data:"); + context.Information($"Repository : {RepositoryHostUrl}/{RepositoryOwner}/{RepositoryName}"); + context.Information($"Git remote name : {Remote}"); + context.Information($"Git reference : {Ref}"); + context.Information($"Branch : {Branch}"); + context.Information($"Build environment : {(IsCI ? "cloud" : "local")}"); + context.Information($"Solution : {SolutionPath.GetFilename()}"); + context.Information($"Version : {Version}"); + context.Information($"Public release : {(IsPublicRelease ? "yes" : "no")}"); + context.Information($"Prerelease : {(IsPrerelease ? "yes" : "no")}"); + } + + /* + * Summary : Gets the repository host URL (e.g. "https://github.com" for a repository hosted on GitHub.) + */ + public string RepositoryHostUrl { get; } + + /* + * Summary : Gets the repository owner (e.g. "Tenacom" for repository Tenacom/SomeLibrary.) + */ + public string RepositoryOwner { get; } + + /* + * Summary : Gets the repository owner (e.g. "SomeLibrary" for repository Tenacom/SomeLibrary.) + */ + public string RepositoryName { get; } + + /* + * Summary : Gets the name of the Git remote that points to the main repository + * (usually "origin" in cloud builds, "upstream" when working locally on a fork.) + */ + public string Remote { get; } + + /* + * Summary : Gets Git's HEAD reference or SHA. + */ + public string Ref { get; private set; } + + /* + * Summary : Gets Git's HEAD branch name, or the empty string if not on a branch. + */ + public string Branch { get; } + + /* + * Summary : Gets the path of the directory where build artifacts are stored. + */ + public DirectoryPath ArtifactsPath { get; } + + /* + * Summary : Gets the path of the directory where test results and coverage reports are stored. + */ + public DirectoryPath TestResultsPath { get; } + + /* + * Summary : Gets the path of the CHANGELOG.md file. + */ + public FilePath ChangelogPath { get; } + + /* + * Summary : Gets the path of the solution file. + */ + public FilePath SolutionPath { get; } + + /* + * Summary : Gets the parsed solution. + */ + public SolutionParserResult Solution { get; } + + /* + * Summary : Gets the configuration to build. + */ + public string Configuration { get; } + + /* + * Summary : Gets the version to build, as a string computed by Nerdbank.GitVersioning. + */ + public string VersionStr { get; private set; } + + /* + * Summary : Gets the version to build, as a SemanticVersion object. + */ + public SemanticVersion Version { get; private set; } + + /* + * Summary : Gets a value that indicates whether a public release can be built. + * Value : True if Git's HEAD is on a public release branch, as indicated in version.json; + * otherwise, false. + */ + public bool IsPublicRelease { get; private set; } + + /* + * Summary : Gets a value that indicates whether the version to build is a prerelease. + */ + public bool IsPrerelease { get; private set; } + + /* + * Summary : Gets a value that indicates whether Cake is running in a GitHub Actions workflow. + */ + public bool IsGitHubAction { get; } + + /* + * Summary : Gets a value that indicates whether Cake is running on a cloud build server. + */ + public bool IsCI { get; } + + /* + * Summary : Gets the MSBuild settings to use for DotNet aliases. + */ + public DotNetMSBuildSettings MSBuildSettings { get; } + + /* + * Summary : Update build configuration data, typically after a commit. + * Params : context - The Cake context. + */ + public void Update(ICakeContext context) + { + (VersionStr, Ref, IsPublicRelease, IsPrerelease) = context.GetVersionInformation(); + Version = SemanticVersion.Parse(VersionStr); + context.Information("Updated build configuration data:"); + context.Information($"Git reference : {Ref}"); + context.Information($"Version : {Version}"); + context.Information($"Public release : {(IsPublicRelease ? "yes" : "no")}"); + context.Information($"Prerelease : {(IsPrerelease ? "yes" : "no")}"); + } +} diff --git a/build/DocFx.cake b/build/DocFx.cake new file mode 100644 index 0000000..5826ebd --- /dev/null +++ b/build/DocFx.cake @@ -0,0 +1,124 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#tool nuget:?package=docfx.console&version=2.59.4 + +#nullable enable + +// --------------------------------------------------------------------------------------------- +// DocFx class +// --------------------------------------------------------------------------------------------- + +using System; +using System.Runtime.InteropServices; + +/* + * Summary : Implements DocFx operations + */ +sealed class DocFx +{ + private const string ToolExeName = "docfx.exe"; + + private readonly DirectoryPath _docsPath; + private FilePath? _docFxPath; + + /* + * Summary : Initializes a new instance of the DocFx class. + * Params : context - The Cake context. + * docsPath - The path to the folder where DocFX operates. + */ + public DocFx(ICakeContext context, BuildData buildData, DirectoryPath docsPath) + { + Context = context; + BuildData = buildData; + _docsPath = docsPath; + } + + private ICakeContext Context { get; } + + private BuildData BuildData { get; } + + /* + * Summary : Extracts language metadata according to docfx.json settings. + */ + public void Metadata() + { + var docFxJsonPath = _docsPath.CombineWithFilePath("docfx.json"); + var json = LoadJsonObject(docFxJsonPath); + if (!json.TryGetPropertyValue("metadata", out _)) + { + Context.Information("No metadata to generate."); + return; + } + + Context.Information("Running DocFx..."); + Run("metadata"); + } + + /* + * Summary : Generates documentation according to docfx.json settings. + */ + public void Build() + { + Context.Information("Running DocFx..."); + Run("build"); + } + + /* + * Summary : Hosts the built documentation web site. + */ + public void Serve() + { + if (BuildData.IsCI) + { + Context.Information("DocFX web server not suitable for cloud builds, skipping."); + return; + } + + Context.Information("Starting DocFX web server..."); + var (_, process) = Start("serve _site"); + Console.WriteLine("Press any key to stop serving..."); + _ = WaitForKey(); + Context.Information("Stopping DocFX web server..."); + process.Kill(); + process.WaitForExit(); + } + + private static ConsoleKeyInfo WaitForKey() + { + while (Console.KeyAvailable) + { + _ = Console.ReadKey(true); + } + + return Console.ReadKey(true); + } + + private void Run(ProcessArgumentBuilder arguments) + { + var (commandName, process) = Start(arguments); + process.WaitForExit(); + var exitCode = process.GetExitCode(); + Ensure(exitCode == 0, $"{commandName} exited with code {exitCode}."); + } + + private (string commandName, IProcess Process) Start(ProcessArgumentBuilder arguments) + { + _docFxPath ??= Context.Tools.Resolve(ToolExeName); + Ensure(_docFxPath != null, $"Cannot find {ToolExeName}"); + FilePath command = _docFxPath; + if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + command = "mono"; + arguments = arguments.PrependQuoted(_docFxPath.FullPath); + } + + var process = Context.StartAndReturnProcess(command, new ProcessSettings() + { + Arguments = arguments, + WorkingDirectory = _docsPath, + }); + + return (command.GetFilenameWithoutExtension().ToString(), process); + } +} diff --git a/build/THIRD-PARTY-NOTICES b/build/THIRD-PARTY-NOTICES new file mode 100644 index 0000000..4b11eb5 --- /dev/null +++ b/build/THIRD-PARTY-NOTICES @@ -0,0 +1,34 @@ +These scripts may use and/or incorporate third-party libraries or other resources +that may be distributed under licenses different than this project. + +In the event that we accidentally failed to list a required notice, please +bring it to our attention. Either post an issue, or email us: + + info@tenacom.it + +The attached notices are provided for information only. + +================================================================================================ +Humanizer - https://github.com/Humanizr/Humanizer +------------------------------------------------------------------------------------------------ +The MIT License (MIT) + +Copyright (c) .NET Foundation and Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/build/changelog.cake b/build/changelog.cake new file mode 100644 index 0000000..a361023 --- /dev/null +++ b/build/changelog.cake @@ -0,0 +1,266 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#nullable enable + +// --------------------------------------------------------------------------------------------- +// Changelog management helpers +// --------------------------------------------------------------------------------------------- + +using System.Globalization; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; + +using SysFile = System.IO.File; + +/* + * Summary : Checks the changelog for contents in the "Unreleased changes" section. + * Params : context - The Cake context. + * changelogPath - The FilePath of the changelog. + * Returns : If there are any contents (excluding blank lines and sub-section headings) + * in the "Unreleased changes" section, true; otherwise, false. + */ +static bool ChangelogHasUnreleasedChanges(this ICakeContext context, FilePath changelogPath) +{ + using (var reader = new StreamReader(changelogPath.FullPath, Encoding.UTF8)) + { + var sectionHeadingRegex = new Regex(@"^ {0,3}##($|[^#])", RegexOptions.Compiled | RegexOptions.CultureInvariant); + var subSectionHeadingRegex = new Regex(@"^ {0,3}###($|[^#])", RegexOptions.Compiled | RegexOptions.CultureInvariant); + string? line; + do + { + line = reader.ReadLine(); + } while (line != null && !sectionHeadingRegex.IsMatch(line)); + + Ensure(line != null, $"{changelogPath.GetFilename()} contains no sections."); + for (; ;) + { + line = reader.ReadLine(); + if (line == null || sectionHeadingRegex.IsMatch(line)) + { + break; + } + + if (!string.IsNullOrWhiteSpace(line) && !subSectionHeadingRegex.IsMatch(line)) + { + return true; + } + } + } + + return false; +} + +/* + * Summary : Prepares the changelog for a release by moving the contents of the "Unreleased changes" section + * to a new section. + * Params : context - The Cake context. + * data - Build configuration data. + */ +static void PrepareChangelogForRelease(this ICakeContext context, BuildData data) +{ + context.Information("Updating changelog..."); + var encoding = new UTF8Encoding(false, true); + var sb = new StringBuilder(); + using (var reader = new StreamReader(data.ChangelogPath.FullPath, encoding)) + using (var writer = new StringWriter(sb, CultureInfo.InvariantCulture)) + { + // Using a StringWriter instead of a StringBuilder allows for a custom line separator + // Under Windows, a StringBuilder would only use "\r\n" as a line separator, which would be wrong in this case + writer.NewLine = "\n"; + var sectionHeadingRegex = new Regex(@"^ {0,3}##($|[^#])", RegexOptions.Compiled | RegexOptions.CultureInvariant); + var subSectionHeadingRegex = new Regex(@"^ {0,3}###($|[^#])", RegexOptions.Compiled | RegexOptions.CultureInvariant); + var subSections = new List<(string Header, List Lines)>(); + subSections.Add(("", new List())); + var subSectionIndex = 0; + + const int ReadingFileHeader = 0; + const int ReadingUnreleasedChangesSection = 1; + const int ReadingRemainderOfFile = 2; + const int ReadingDone = 3; + var state = ReadingFileHeader; + while (state != ReadingDone) + { + var line = reader.ReadLine(); + switch (state) + { + case ReadingFileHeader: + Ensure(line != null, $"{data.ChangelogPath.GetFilename()} contains no sections."); + + // Copy everything up to an including the first section heading (which we assume is "Unreleased changes") + writer.WriteLine(line); + if (sectionHeadingRegex.IsMatch(line)) + { + state = ReadingUnreleasedChangesSection; + } + + break; + case ReadingUnreleasedChangesSection: + if (line == null) + { + // The changelog only contains the "Unreleased changes" section; + // this happens when no release has been published yet + WriteNewSections(true); + state = ReadingDone; + break; + } + + if (sectionHeadingRegex.IsMatch(line)) + { + // Reached header of next section + WriteNewSections(false); + writer.WriteLine(line); + state = ReadingRemainderOfFile; + break; + } + + if (subSectionHeadingRegex.IsMatch(line)) + { + subSections.Add((line, new List())); + ++subSectionIndex; + break; + } + + subSections[subSectionIndex].Lines.Add(line); + break; + case ReadingRemainderOfFile: + if (line == null) + { + state = ReadingDone; + break; + } + + writer.WriteLine(line); + break; + default: + Fail($"Internal error: reading state corrupted ({state})."); + throw null; + } + } + + void WriteNewSections(bool atEndOfFile) + { + // Create empty sub-sections in new "Unreleased changes" section + foreach (var subSection in subSections.Skip(1)) + { + writer.WriteLine(string.Empty); + writer.WriteLine(subSection.Header); + } + + // Write header of new release section + writer.WriteLine(string.Empty); + writer.WriteLine("## " + MakeChangelogSectionTitle(data)); + + var newSectionLines = CollectNewSectionLines(); + var newSectionCount = newSectionLines.Count; + if (atEndOfFile) + { + // If there is no other section after the new release, + // we don't want extra blank lines at EOF + while (newSectionCount > 0 && string.IsNullOrEmpty(newSectionLines[newSectionCount - 1])) + { + --newSectionCount; + } + } + + foreach (var newSectionLine in newSectionLines.Take(newSectionCount)) + { + writer.WriteLine(newSectionLine); + } + } + + List CollectNewSectionLines() + { + var result = new List(subSections[0].Lines); + + // Copy only sub-sections that have actual content + foreach (var subSection in subSections.Skip(1).Where(s => s.Lines.Any(l => !string.IsNullOrWhiteSpace(l)))) + { + result.Add(subSection.Header); + foreach (var contentLine in subSection.Lines) + { + result.Add(contentLine); + } + } + + return result; + } + } + + SysFile.WriteAllText(data.ChangelogPath.FullPath, sb.ToString(), encoding); +} + +/* + * Summary : Updates the heading of the first section of the changelog after the "Unreleased changes" section + * to reflect a change in the released version. + * Params : context - The Cake context. + * data - Build configuratiohn data. + */ +static void UpdateChangelogNewSectionTitle(this ICakeContext context, BuildData data) +{ + context.Information("Updating changelog's new release section title..."); + var encoding = new UTF8Encoding(false, true); + var sb = new StringBuilder(); + using (var reader = new StreamReader(data.ChangelogPath.FullPath, encoding)) + using (var writer = new StringWriter(sb, CultureInfo.InvariantCulture)) + { + // Using a StringWriter instead of a StringBuilder allows for a custom line separator + // Under Windows, a StringBuilder would only use "\r\n" as a line separator, which would be wrong in this case + writer.NewLine = "\n"; + var sectionHeadingRegex = new Regex(@"^ {0,3}##($|[^#])", RegexOptions.Compiled | RegexOptions.CultureInvariant); + + const int ReadingFileHeader = 0; + const int ReadingUnreleasedChangesSection = 1; + const int ReadingRemainderOfFile = 2; + const int ReadingDone = 3; + var state = ReadingFileHeader; + while (state != ReadingDone) + { + var line = reader.ReadLine(); + switch (state) + { + case ReadingFileHeader: + Ensure(line != null, $"{data.ChangelogPath.GetFilename()} contains no sections."); + writer.WriteLine(line); + if (sectionHeadingRegex.IsMatch(line)) + { + state = ReadingUnreleasedChangesSection; + } + + break; + case ReadingUnreleasedChangesSection: + Ensure(line != null, $"{data.ChangelogPath.GetFilename()} contains only one section."); + if (sectionHeadingRegex.IsMatch(line)) + { + // Replace header of second section + writer.WriteLine("## " + MakeChangelogSectionTitle(data)); + state = ReadingRemainderOfFile; + break; + } + + writer.WriteLine(line); + break; + case ReadingRemainderOfFile: + if (line == null) + { + state = ReadingDone; + break; + } + + writer.WriteLine(line); + break; + default: + Fail($"Internal error: reading state corrupted ({state})."); + throw null; + } + } + } + + SysFile.WriteAllText(data.ChangelogPath.FullPath, sb.ToString(), encoding); +} + +static string MakeChangelogSectionTitle(BuildData data) +{ + return $"[{data.VersionStr}](https://github.com/{data.RepositoryOwner}/{data.RepositoryName}/releases/tag/{data.VersionStr}) ({DateTime.Now:yyyy-MM-dd})"; +} diff --git a/build/dotnet.cake b/build/dotnet.cake new file mode 100644 index 0000000..f6824c2 --- /dev/null +++ b/build/dotnet.cake @@ -0,0 +1,143 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#nullable enable + +// --------------------------------------------------------------------------------------------- +// .NET SDK helpers +// --------------------------------------------------------------------------------------------- + +using System.IO; +using System.Linq; + +using SysDirectory = System.IO.Directory; +using SysPath = System.IO.Path; + +/* + * Summary : Restore all NuGet packages for the solution. + * Params : context - The Cake context. + * data - Build configuration data. + */ +static void RestoreSolution(this ICakeContext context, BuildData data) +{ + context.Information("Restoring NuGet packages for solution..."); + context.DotNetRestore(data.SolutionPath.FullPath, new() { + DisableParallel = true, + Interactive = false, + MSBuildSettings = data.MSBuildSettings, + }); +} + +/* + * Summary : Build all projects in teh solution. + * Params : context - The Cake context. + * data - Build configuration data. + * restore - true to restore NuGet packages before building, false otherwise. + */ +static void BuildSolution(this ICakeContext context, BuildData data, bool restore) +{ + context.Information($"Building solution (restore = {restore})..."); + context.DotNetBuild(data.SolutionPath.FullPath, new() { + Configuration = data.Configuration, + MSBuildSettings = data.MSBuildSettings, + NoLogo = true, + NoRestore = !restore, + }); +} + +/* + * Summary : Run all unit tests for the solution. + * Params : context - The Cake context. + * data - Build configuration data. + * restore - true to restore NuGet packages before testing, false otherwise. + * build - true to build the solution before testing, false otherwise. + * collect - true to collect coverage data with Coverlet + * Remarks : If successful, this method will merge all coverage reports generated by VSTest + * into a single file suitable for upload to Codecov. + */ +static void TestSolution(this ICakeContext context, BuildData data, bool restore, bool build, bool collect) +{ + context.Information($"Running tests (restore = {restore}, build = {build}, collect = {collect})..."); + context.DotNetTest(data.SolutionPath.FullPath, new() { + Configuration = data.Configuration, + NoBuild = !build, + NoLogo = true, + NoRestore = !restore, + ArgumentCustomization = args => collect + ? args.Append("--collect:\"XPlat Code Coverage\"") + : args, + }); + + // Merge coverage reports only if there are any + if (collect) + { + if (!context.FileSystem.Exist(data.TestResultsPath) || !context.GetSubDirectories(data.TestResultsPath).Any()) + { + context.Information("No coverage reports were generated."); + } + else + { + context.Information("Merging coverage reports..."); + const string CoverageDataFileName = "coverage.cobertura.xml"; + var coverageDataGlob = SysPath.Combine(data.TestResultsPath.FullPath, "*", CoverageDataFileName); + context.DotNetTool($"reportgenerator \"-reports:{coverageDataGlob}\" \"-targetDir:{data.TestResultsPath.FullPath}\" -reporttypes:Cobertura"); + } + } +} + +/* + * Summary : Run the Pack target on the solution. This usually produces NuGet packages, + * but Buildvana SDK may hijack the target to produce, for example, setup executables. + * Params : context - The Cake context. + * data - Build configuration data. + * restore - true to restore NuGet packages before packing, false otherwise. + * build - true to build the solution before packing, false otherwise. + */ +static void PackSolution(this ICakeContext context, BuildData data, bool restore, bool build) +{ + context.Information($"Packing solution (restore = {restore}, build = {build})..."); + context.DotNetPack(data.SolutionPath.FullPath, new() { + Configuration = data.Configuration, + MSBuildSettings = data.MSBuildSettings, + NoBuild = !build, + NoLogo = true, + NoRestore = !restore, + }); +} + +/* + * Summary : Push all produced NuGet packages to the appropriate NuGet server. + * Params : context - The Cake context. + * data - Build configuration data. + * Remarks : - This method uses the following environment variables: + * * PRERELEASE_NUGET_SOURCE - NuGet source URL where to push prerelease packages + * * RELEASE_NUGET_SOURCE - NuGet source URL where to push non-prerelease packages + * * PRERELEASE_NUGET_KEY - API key for PRERELEASE_NUGET_SOURCE + * * RELEASE_NUGET_KEY - API key for RELEASE_NUGET_SOURCE + * - If there are no .nupkg files in the designated artifacts directory, this method does nothing. + */ +static void NuGetPushAll(this ICakeContext context, BuildData data) +{ + const string nupkgMask = "*.nupkg"; + if (!SysDirectory.EnumerateFiles(data.ArtifactsPath.FullPath, nupkgMask).Any()) + { + context.Verbose("No .nupkg files to push."); + return; + } + + var nugetSource = context.GetOptionOrFail(data.IsPrerelease ? "prereleaseNugetSource" : "releaseNugetSource"); + var nugetApiKey = context.GetOptionOrFail(data.IsPrerelease ? "prereleaseNugetKey" : "releaseNugetKey"); + var nugetPushSettings = new DotNetNuGetPushSettings { + ForceEnglishOutput = true, + Source = nugetSource, + ApiKey = nugetApiKey, + SkipDuplicate = true, + }; + + var packages = SysPath.Combine(data.ArtifactsPath.FullPath, nupkgMask); + foreach (var path in context.GetFiles(packages)) + { + context.Information($"Pushing {path} to {nugetSource}..."); + context.DotNetNuGetPush(path, nugetPushSettings); + } +} diff --git a/build/environment.cake b/build/environment.cake new file mode 100644 index 0000000..0419bec --- /dev/null +++ b/build/environment.cake @@ -0,0 +1,28 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#nullable enable + +// --------------------------------------------------------------------------------------------- +// Environment helpers +// --------------------------------------------------------------------------------------------- + +/* + * Summary : Gets a string from the environment, failing if the value is not found or is the empty string. + * Params : name - The name of the environment variable to read. + * fallbackName - The name of another environment variable to read if name is not found or its value is the empty string. + * Returns : The value of an environment variable. + */ +string GetEnvironmentString(string name, string fallbackName = "") +{ + var result = EnvironmentVariable(name, string.Empty); + if (!string.IsNullOrEmpty(result)) + { + return result; + } + + Ensure(!string.IsNullOrEmpty(fallbackName), $"Environment variable {name} is missing or has an empty value."); + result = EnvironmentVariable(fallbackName, string.Empty); + Ensure(!string.IsNullOrEmpty(result), 255, $"Both environment variables {name} and {fallbackName} are missing or have an empty value."); + return result; +} diff --git a/build/fail.cake b/build/fail.cake new file mode 100644 index 0000000..0a8745d --- /dev/null +++ b/build/fail.cake @@ -0,0 +1,75 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#nullable enable + +// --------------------------------------------------------------------------------------------- +// Build failure helpers +// --------------------------------------------------------------------------------------------- + +using System.Diagnostics.CodeAnalysis; + +/* + * Summary : Fails the build with the specified message. + * This method does not return. + * Params : message - A message explaining the reason for failing the build. + */ +[DoesNotReturn] +static void Fail(string message) => throw new CakeException(message); + +/* + * Summary : Fails the build with the specified message. + * This method does not return. + * Type : T - The expected return type. + * Params : message - A message explaining the reason for failing the build. + * Returns : This method never returns. + */ +[DoesNotReturn] +static T Fail(string message) => throw new CakeException(message); + +/* + * Summary : Fails the build with the specified exit code and message. + * This method does not return. + * Params : exitCode - The Cake exit code. + * message - A message explaining the reason for failing the build. + */ +[DoesNotReturn] +static void Fail(int exitCode, string message) => throw new CakeException(exitCode, message); + +/* + * Summary : Fails the build with the specified exit code and message. + * This method does not return. + * Type : T - The expected return type. + * Params : exitCode - The Cake exit code. + * message - A message explaining the reason for failing the build. + * Returns : This method never returns. + */ +[DoesNotReturn] +static T Fail(int exitCode, string message) => throw new CakeException(exitCode, message); + +/* + * Summary : Fails the build with the specified message if a condition is not verified. + * Params : condition - The condition to verify. + * message - A message explaining the reason for failing the build. + */ +static void Ensure([DoesNotReturnIf(false)] bool condition, string message) +{ + if (!condition) + { + throw new CakeException(message); + } +} + +/* + * Summary : Fails the build with the specified message if a condition is not verified. + * Params : condition - The condition to verify. + * exitCode - The Cake exit code. + * message - A message explaining the reason for failing the build. + */ +static void Ensure([DoesNotReturnIf(false)] bool condition, int exitCode, string message) +{ + if (!condition) + { + throw new CakeException(exitCode, message); + } +} diff --git a/build/filesystem.cake b/build/filesystem.cake new file mode 100644 index 0000000..1a541f9 --- /dev/null +++ b/build/filesystem.cake @@ -0,0 +1,25 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#nullable enable + +// --------------------------------------------------------------------------------------------- +// File system helpers +// --------------------------------------------------------------------------------------------- + +/* + * Summary : Delete a directory, including its contents, if it exists. + * Params : context - The Cake context. + * directory - The directory to delete. + */ +static void DeleteDirectoryIfExists(this ICakeContext context, DirectoryPath directory) +{ + if (!context.DirectoryExists(directory)) + { + context.Verbose($"Skipping non-existent directory: {directory}"); + return; + } + + context.Information($"Deleting directory: {directory}"); + context.DeleteDirectory(directory, new() { Force = false, Recursive = true }); +} diff --git a/build/git.cake b/build/git.cake new file mode 100644 index 0000000..ede3aba --- /dev/null +++ b/build/git.cake @@ -0,0 +1,180 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#nullable enable + +// --------------------------------------------------------------------------------------------- +// Git repository helpers +// --------------------------------------------------------------------------------------------- + +using System; +using System.Linq; + +/* + * Summary : Gets the name of the current Git branch. + * Params : context - The Cake context. + * Returns : If HEAD is on a branch, the name of the branch; otherwise, the empty string. + */ +static string GetCurrentGitBranch(this ICakeContext context) => context.Exec("git", "branch --show-current").FirstOrDefault(string.Empty); + +/* + * Summary : Attempts to get information about the remote repository. + * Params : context - The Cake context. + * Returns : Remote - The Git remote name. + * HostUrl - The base URL of the Git repository host. + * Owner - The repository owner. + * Name - The repository name. + * Remarks : - If the githubRepository argument is given, or the GITHUB_REPOSITORY environment variable is set + * (as it happens in GitHub Actions,) Owner and Name are taken from there, while Remote is set + * to the first Git remote found whose fetch URL matches them. + * - If GITHUB_REPOSITORY is not available, Git remote fetch URLs are parsed for Owner and Name; + * remotes "upstream" and "origin" are tested, in that order, in case "origin" is a fork. + */ +static bool TryGetRepositoryInfo(this ICakeContext context, out (string Remote, string HostUrl, string Owner, string Name) result) +{ + return TryGetRepositoryInfoFromGitHubActions(out result) + || TryGetRepositoryInfoFromGitRemote("upstream", out result) + || TryGetRepositoryInfoFromGitRemote("origin", out result); + + bool TryGetRepositoryInfoFromGitHubActions(out (string Remote, string HostUrl, string Owner, string Name) result) + { + var repository = context.GetOption("githubRepository", string.Empty); + if (string.IsNullOrEmpty(repository)) + { + result = default; + return false; + } + + var hostUrl = context.GetOptionOrFail("githubServerUrl"); + var segments = repository.Split('/'); + foreach (var remote in context.Exec("git", "remote")) + { + if (TryGetRepositoryInfoFromGitRemote(remote, out result) + && string.Equals(result.HostUrl, hostUrl, StringComparison.Ordinal) + && string.Equals(result.Owner, segments[0], StringComparison.Ordinal) + && string.Equals(result.Name, segments[1], StringComparison.Ordinal)) + { + return true; + } + } + + result = default; + return false; + } + + bool TryGetRepositoryInfoFromGitRemote(string remote, out (string Remote, string HostUrl, string Owner, string Name) result) + { + if (context.Exec("git", "remote get-url " + remote, out var output) != 0) + { + result = default; + return false; + } + + var url = output.FirstOrDefault(); + if (string.IsNullOrEmpty(url)) + { + result = default; + return false; + } + + Uri uri; + try + { + uri = new Uri(url); + } + catch (UriFormatException) + { + result = default; + return false; + } + + var path = uri.AbsolutePath; + path = path.EndsWith(".git", StringComparison.Ordinal) + ? path.Substring(1, path.Length - 5) + : path.Substring(1); + + var segments = path.Split('/'); + if (segments.Length != 2) + { + result = default; + return false; + } + + result = (remote, $"{uri.Scheme}://{uri.Host}{(uri.IsDefaultPort ? null : ":" + uri.Port.ToString())}", segments[0], segments[1]); + return true; + } +} + +/* + * Summary : Tells whether a tag exists in the local Git repository. + * Params : context - The Cake context. + * tag - The tag to check for. + * Returns : True if the tag exists; false otherwise. + */ +static bool GitTagExists(this ICakeContext context, string tag) => context.Exec("git", "tag").Any(s => string.Equals(tag, s, StringComparison.Ordinal)); + +/* + * Summary : Gets the latest version and the latest stable version in commit history. + * Params : context - The Cake context. + * Returns : A tuple of the latest version and the latest stable version; + * Remarks : - If no version tag is found in commit history, this method returns a tuple of two nulls. + * - If no stable version tag is found in commit history, this method returns a tuple of the latest version and null. + */ +static (SemanticVersion? Latest, SemanticVersion? LatestStable) GitGetLatestVersions(this ICakeContext context) +{ + context.Verbose("Looking for latest stable version tag in Git commit history..."); + var output = context.Exec("git", "log --pretty=format:%D"); + var versions = output.Where(static x => !string.IsNullOrEmpty(x)) + .SelectMany(static x => x.Split(", ")) + .Where(static x => x.StartsWith("tag: ")) + .Select(static x => x.Substring(5)) + .Select(static x => { + SemanticVersion? version = null; + var result = SemanticVersion.TryParse(x, out version); + return version; + }) + .Where(static x => x != null); + + SemanticVersion? latest = null; + SemanticVersion? latestStable = null; + foreach (var version in versions) + { + if (latest == null) + { + latest = version; + } + + if (!version.IsPrerelease) + { + latestStable = version; + break; + } + } + + return (latest, latestStable); +} + +/* + * Summary : Sets Git user name and email. + * Params : context - The Cake context. + * name - The name of the user. + * email - The email address of the user. + */ +static void GitSetUserIdentity(this ICakeContext context, string name, string email) +{ + context.Information($"Setting Git user name to '{name}'..."); + _ = context.Exec( + "git", + new ProcessArgumentBuilder() + .Append("config") + .Append("user.name") + .AppendQuoted(name)); + + context.Information($"Setting Git user email to '{email}'..."); + _ = context.Exec( + "git", + new ProcessArgumentBuilder() + .Append("config") + .Append("user.email") + .AppendQuoted(email)); +} diff --git a/build/github.cake b/build/github.cake new file mode 100644 index 0000000..020737e --- /dev/null +++ b/build/github.cake @@ -0,0 +1,151 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#addin nuget:?package=Cake.Http&version=2.0.0 +#addin nuget:?package=Octokit&version=3.0.1 + +#nullable enable + +// --------------------------------------------------------------------------------------------- +// GitHub API helpers +// --------------------------------------------------------------------------------------------- + +using System.Threading.Tasks; +using Octokit; + +using SysFile = System.IO.File; + +/* + * Summary : Asynchronously creates a new draft release on the GitHub repository. + * Params : context - The Cake context. + * data - Build configuration data. + * Returns : A Task, representing the ongoing operation, whose value will be the ID of the newly created release. + */ +static async Task CreateDraftReleaseAsync(this ICakeContext context, BuildData data) +{ + var tag = data.VersionStr; + var client = context.CreateGitHubClient(); + context.Information($"Creating a provisional draft release..."); + var newRelease = new NewRelease(tag) + { + Name = $"{tag} [provisional]", + TargetCommitish = data.Branch, + Prerelease = data.IsPrerelease, + Draft = true, + }; + + var createReleaseResponse = await client.Repository.Release.Create(data.RepositoryOwner, data.RepositoryName, newRelease).ConfigureAwait(false); + return createReleaseResponse.Id; +} + +/* + * Summary : Asynchronously publishes a draft release on the GitHub repository. + * Params : context - The Cake context. + * data - Build configuration data. + * id - The ID of the release. + * Returns : A Task that represents the ongoing operation. + */ +static async Task PublishReleaseAsync(this ICakeContext context, BuildData data, int id) +{ + var tag = data.VersionStr; + var client = context.CreateGitHubClient(); + context.Information($"Generating release notes for {tag}..."); + var releaseNotesRequest = new GenerateReleaseNotesRequest(tag) + { + TargetCommitish = data.Branch, + }; + + var generateNotesResponse = await client.Repository.Release.GenerateReleaseNotes(data.RepositoryOwner, data.RepositoryName, releaseNotesRequest).ConfigureAwait(false); + var body = $"We also have a [human-curated changelog]({data.RepositoryHostUrl}/{data.RepositoryOwner}/{data.RepositoryName}/blob/main/CHANGELOG.md).\n\n---\n\n" + + generateNotesResponse.Body; + + context.Information($"Publishing the previously created release as {tag}..."); + var update = new ReleaseUpdate + { + TagName = tag, + Name = tag, + Body = body, + Prerelease = data.IsPrerelease, + Draft = false, + }; + + _ = await client.Repository.Release.Edit(data.RepositoryOwner, data.RepositoryName, id, update).ConfigureAwait(false); +} + +/* + * Summary : Asynchronously deletes a release and, optionally, the corresponding tag on the GitHub repository. + * Params : context - The Cake context. + * data - Build configuration data. + * id - The ID of the release. + * tagName - The tag name, or null to not delete a tag. + * Returns : A Task that represents the ongoing operation. + */ +static async Task DeleteReleaseAsync(this ICakeContext context, BuildData data, int id, string? tagName) +{ + context.Information("Deleting the previously created release..."); + var client = context.CreateGitHubClient(); + await client.Repository.Release.Delete(data.RepositoryOwner, data.RepositoryName, id).ConfigureAwait(false); + if (tagName != null) + { + var reference = "refs/tags/" + tagName; + context.Information($"Looking for reference '{reference}' in GitHub repository..."); + try + { + _ = await client.Git.Reference.Get(data.RepositoryOwner, data.RepositoryName, reference).ConfigureAwait(false); + } + catch (NotFoundException) + { + context.Information($"Reference '{reference}' not found in GitHub repository."); + return; + } + + context.Information($"Deleting reference '{reference}' in GitHub repository..."); + await client.Git.Reference.Delete(data.RepositoryOwner, data.RepositoryName, reference).ConfigureAwait(false); + } +} + +/* + * Summary : Asynchronously creates a workflow dispatch event on the GitHub repository. + * Params : context - The Cake context. + * data - Build configuration data. + * filename - The name of the workflow file to run, including extension. + * ref - The branch or tag on which to dispatch the workflow run. + * inputs - An optional anonymous object containing the inputs for the workflow. + * Returns : A Task that represents the ongoing operation. + */ +static async Task DispatchWorkflow(this ICakeContext context, BuildData data, string filename, string @ref, object? inputs = null) +{ + context.Information($"Dispatching workflow '{filename}' on '{@ref}'..."); + object requestBody = inputs == null + ? new { @ref = @ref } + : new { @ref = @ref, inputs = inputs }; + + var httpSettings = new HttpSettings() + .SetAccept("application/vnd.github.v3") + .AppendHeader("Authorization", "Token " + context.GetOptionOrFail("githubToken")) + .AppendHeader("User-Agent", "Buildvana (Win32NT 10.0.19044; amd64; en-US)") + .SetJsonRequestBody(requestBody) + .EnsureSuccessStatusCode(true); + + _ = await context.HttpPostAsync($"https://api.github.com/repos/{data.RepositoryOwner}/{data.RepositoryName}/actions/workflows/{filename}/dispatches", httpSettings); +} + +/* + * Summary : Sets a GitHub Actions step output. + * Params : context - The Cake context. + * name - The output name. + * value - The output value. + */ +static void SetActionsStepOutput(this ICakeContext context, string name, string value) +{ + var outputFile = context.EnvironmentVariable("GITHUB_OUTPUT"); + Ensure(!string.IsNullOrEmpty(outputFile), "Cannot set Actions step output: GITHUB_OUTPUT not set."); + SysFile.AppendAllLines(outputFile, new[] { $"{name}={value}" }, Encoding.UTF8); +} + +static GitHubClient CreateGitHubClient(this ICakeContext context) +{ + var client = new GitHubClient(new ProductHeaderValue("Buildvana")); + client.Credentials = new Credentials(context.GetOptionOrFail("githubToken")); + return client; +} diff --git a/build/json.cake b/build/json.cake new file mode 100644 index 0000000..a6f6e03 --- /dev/null +++ b/build/json.cake @@ -0,0 +1,137 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#nullable enable + +// --------------------------------------------------------------------------------------------- +// JSON helpers +// --------------------------------------------------------------------------------------------- + +using System.Text.Encodings.Web; +using System.Text.Json; +using System.Text.Json.Nodes; + +using SysFile = System.IO.File; + +/* + * Summary : Parses a JSON object from a string. Fails the build if not successful. + * Params : str - The string to parse. + * description - A description of the string for exception messages. + * Returns : The parsed object. + */ +static JsonObject ParseJsonObject(string str, string description = "The provided string") +{ + JsonNode? node; + try + { + node = JsonNode.Parse( + str, + new JsonNodeOptions { PropertyNameCaseInsensitive = false }, + new JsonDocumentOptions + { + AllowTrailingCommas = true, + CommentHandling = JsonCommentHandling.Skip, + }); + } + catch (JsonException) + { + Fail($"{description} is not valid JSON."); + throw null; + } + + return node switch { + null => Fail($"{description} was parsed as JSON null."), + JsonObject obj => obj, + object other => Fail($"{description} was parsed as a {other.GetType().Name}, not a {nameof(JsonObject)}."), + }; +} + +/* + * Summary : Loads a JSON object from a file. Fails the build if not successful. + * Params : path - The path of the file to parse. + * Returns : The parsed object. + */ +static JsonObject LoadJsonObject(FilePath path) +{ + var fullPath = path.FullPath; + JsonNode? node; + try + { + using var stream = SysFile.OpenRead(fullPath); + node = JsonNode.Parse( + stream, + new JsonNodeOptions { PropertyNameCaseInsensitive = false }, + new JsonDocumentOptions + { + AllowTrailingCommas = true, + CommentHandling = JsonCommentHandling.Skip, + }); + } + catch (IOException e) + { + Fail($"Could not read from {fullPath}: {e.Message}"); + throw null; + } + catch (JsonException) + { + Fail($"{fullPath} does not contain valid JSON."); + throw null; + } + + return node switch { + null => Fail($"{fullPath} was parsed as JSON null."), + JsonObject obj => obj, + object other => Fail($"{fullPath} was parsed as a {other.GetType().Name}, not a {nameof(JsonObject)}."), + }; +} + +/* + * Summary : Saves a JSON object to a file. Fails the build if not successful. + * Params : path - The path of the file to parse. + * Returns : The parsed object. + */ +static void SaveJson(JsonNode json, FilePath path) +{ + var fullPath = path.FullPath; + try + { + using var stream = SysFile.OpenWrite(fullPath); + var writerOptions = new JsonWriterOptions + { + Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping, + Indented = true, + }; + + using var writer = new Utf8JsonWriter(stream, writerOptions); + json.WriteTo(writer); + stream.SetLength(stream.Position); + } + catch (IOException e) + { + Fail($"Could not write to {fullPath}: {e.Message}"); + throw null; + } +} + +/* + * Summary : Gets the value of a property from a JSON object. Fails the build if not successful. + * Types : T - The desired type of the property value. + * Params : json - The JSON object. + * propertyName - The name of the property to get. + * description - A description of the object for exception messages. + * Returns : The value of the specified property. + */ +static T GetJsonPropertyValue(JsonObject json, string propertyName, string objectDescription = "JSON object") +{ + Ensure(json.TryGetPropertyValue(propertyName, out var property), $"Json property {propertyName} not found in {objectDescription}."); + switch (property) + { + case null: + return Fail($"Json property {propertyName} in {objectDescription} is null."); + case JsonValue value: + Ensure(value.TryGetValue(out var result), $"Json property {propertyName} in {objectDescription} cannot be converted to a {typeof(T).Name}."); + return result ?? Fail($"Json property {propertyName} in {objectDescription} has a null value."); + default: + return Fail($"Json property {propertyName} in {objectDescription} is a {property.GetType().Name}, not a {nameof(JsonValue)}."); + } +} diff --git a/build/nbgv.cake b/build/nbgv.cake new file mode 100644 index 0000000..10277c1 --- /dev/null +++ b/build/nbgv.cake @@ -0,0 +1,41 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#nullable enable + +// --------------------------------------------------------------------------------------------- +// Nerdbank.GitVersioning helpers +// --------------------------------------------------------------------------------------------- + +using System.Text; +using System.Text.Json.Nodes; + +/* + * Summary : Gets version information using the NBGV tool. + * Params : context - The Cake context. + * Returns : VersionStr - The project version. + * Ref - The Git ref from which we are building. + * IsPublicRelease - True if a public release can be built, false otherwise. + * IsPrerelease - True if the project version is tagged as prerelease, false otherwise. + */ +static (string VersionStr, string Ref, bool IsPublicRelease, bool IsPrerelease) GetVersionInformation(this ICakeContext context) +{ + var nbgvOutput = new StringBuilder(); + context.DotNetTool( + "nbgv get-version --format json", + new DotNetToolSettings { + SetupProcessSettings = s => s + .SetRedirectStandardOutput(true) + .SetRedirectedStandardOutputHandler(x => { + nbgvOutput.AppendLine(x); + return x; + }), + }); + + var json = ParseJsonObject(nbgvOutput.ToString(), "The output of nbgv"); + return ( + VersionStr: GetJsonPropertyValue(json, "NuGetPackageVersion", "the output of nbgv"), + Ref: GetJsonPropertyValue(json, "BuildingRef", "the output of nbgv"), + IsPublicRelease: GetJsonPropertyValue(json, "PublicRelease", "the output of nbgv"), + IsPrerelease: !string.IsNullOrEmpty(GetJsonPropertyValue(json, "PrereleaseVersion", "the output of nbgv"))); +} diff --git a/build/options.cake b/build/options.cake new file mode 100644 index 0000000..27d06f5 --- /dev/null +++ b/build/options.cake @@ -0,0 +1,144 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#nullable enable + +// --------------------------------------------------------------------------------------------- +// Option helpers +// --------------------------------------------------------------------------------------------- + +using System.ComponentModel; +using System.Linq; + +/* + * Summary : Tells whether the specified option is present, either as an argument + * or as an environment variable. + * Params : context - The Cake context. + * name - The option name. + * environmentPrefix - An optional prefix for the environment variable name; + * for example, camelCasedOption (prefix = "MYAPP_") -> MYAPP_CAMEL_CASED_OPTION + * Returns : If an argument with the specified name is present, true; + * if an environment variable with the specified name (converted according to environmentPrefix) + * is present, true; otherwise, false. + */ +static bool HasOption(this ICakeContext context, string name, string? environmentPrefix = null) + => context.HasArgument(name) || context.HasEnvironmentVariable(OptionNameToEnvironmentVariableName(name, environmentPrefix)); + +/* + * Summary : Gets an option from, in this order: + * * a command line argument with the specified name; + * * an environment variable with the specified name converted to UNDERSCORE_UPPER_CASE; + * * the provided default value. + * Params : context - The Cake context. + * name - The option name. + * defaultValue - The value returned if neither a corresponding argument + * nor environment variable was found. + */ +static T GetOption(this ICakeContext context, string name, T defaultValue) + where T : notnull + => context.GetOption(name, null, defaultValue); + +/* + * Summary : Gets an option from, in this order: + * * a command line argument with the specified name; + * * an environment variable with the specified name converted to UNDERSCORE_UPPER_CASE + * and optionally prefixed with the specified environmentPrefix; + * * the provided default value. + * Params : context - The Cake context. + * name - The option name. + * environmentPrefix - An optional prefix for the environment variable name; + * for example, "camelCasedOption" with an environmentPrefix + * of "MYAPP_" becomes "MYAPP_CAMEL_CASED_OPTION". + * defaultValue - The value returned if neither a corresponding argument + * nor environment variable was found. + */ +static T GetOption(this ICakeContext context, string name, string? environmentPrefix, T defaultValue) + where T : notnull +{ + var value = context.Arguments.GetArguments(name)?.FirstOrDefault(); + if (value != null) + { + return ConvertOption(value); + } + + value = context.Environment.GetEnvironmentVariable(OptionNameToEnvironmentVariableName(name, environmentPrefix)); + return value == null ? defaultValue : ConvertOption(value); +} + +/* + * Summary : Gets an option from, in this order: + * * a command line argument with the specified name; + * * an environment variable with the specified name converted to UNDERSCORE_UPPER_CASE; + * * the provided default value. + * Throw an exception if the option is not found or has an empty value. + * Params : context - The Cake context. + * name - The option name. + */ +static T GetOptionOrFail(this ICakeContext context, string name) + where T : notnull + => context.GetOptionOrFail(name, null); + +/* + * Summary : Gets an option from, in this order: + * * a command line argument with the specified name; + * * an environment variable with the specified name converted to UNDERSCORE_UPPER_CASE + * and optionally prefixed with the specified environmentPrefix; + * * the provided default value. + * Throw an exception if the option is not found or has an empty value. + * Params : context - The Cake context. + * name - The option name. + * environmentPrefix - An optional prefix for the environment variable name; + * for example, "camelCasedOption" with an environmentPrefix + * of "MYAPP_" becomes "MYAPP_CAMEL_CASED_OPTION". + */ +static T GetOptionOrFail(this ICakeContext context, string name, string? environmentPrefix) + where T : notnull +{ + var value = context.Arguments.GetArguments(name)?.FirstOrDefault(); + if (value != null) + { + return ConvertOption(value); + } + + var envName = OptionNameToEnvironmentVariableName(name, environmentPrefix); + value = context.Environment.GetEnvironmentVariable(envName); + if (value != null) + { + return ConvertOption(value); + } + + throw new CakeException($"Option {name} / environment variable {envName} not found or empty."); +} + +/* + * Summary : Converts an option name (which is supposed to be in camelCase) + * to an environment variable name (UNDERSCORE_UPPER_CASE). + * Params : prefix - An optional prefix for the environment variable name; + * for example, camelCasedOption (prefix = "MYAPP_") -> MYAPP_CAMEL_CASED_OPTION + */ +// Copyright (c) .NET Foundation and Contributors - MIT License - https://github.com/Humanizr/Humanizer +static string OptionNameToEnvironmentVariableName(string name, string? prefix = null) + => (prefix ?? string.Empty) + Regex.Replace( + Regex.Replace( + Regex.Replace( + name, + @"([\p{Lu}]+)([\p{Lu}][\p{Ll}])", + "$1_$2"), + @"([\p{Ll}\d])([\p{Lu}])", + "$1_$2"), + @"[-\s]", + "_") + .ToUpperInvariant(); + +/* + * Summary : Convert an option to the desired type. + * Types : T - The type to convert the option to. + * Params : value - The value of the option. + * Returns : The converted value. + */ +static T ConvertOption(string value) + where T : notnull +{ + var converter = TypeDescriptor.GetConverter(typeof(T)); + return (T)converter.ConvertFromInvariantString(value)!; +} diff --git a/build/process.cake b/build/process.cake new file mode 100644 index 0000000..0164906 --- /dev/null +++ b/build/process.cake @@ -0,0 +1,38 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#nullable enable + +// --------------------------------------------------------------------------------------------- +// Process helpers +// --------------------------------------------------------------------------------------------- + +using System.Collections.Generic; + +/* + * Summary : Executes an external command, capturing standard output and failing if the exit code is not zero. + * Params : context - The Cake context. + * command - The name of the command to execute. + * arguments - The arguments to pass to the command. + * Returns : The captured output of the command. + */ +static IEnumerable Exec(this ICakeContext context, string command, ProcessArgumentBuilder arguments) +{ + var exitCode = context.Exec(command, arguments, out var output); + Ensure(exitCode == 0, $"'{command} {arguments.RenderSafe()}' exited with code {exitCode}."); + return output; +} + +/* + * Summary : Executes an external command, capturing standard output and failing if the exit code is not zero. + * Params : context - The Cake context. + * command - The name of the command to execute. + * arguments - The arguments to pass to the command. + * out output - The captured output of the command. + * Returns : The exit code of the command. + */ +static int Exec(this ICakeContext context, string command, ProcessArgumentBuilder arguments, out IEnumerable output) + => context.StartProcess( + command, + new ProcessSettings { Arguments = arguments, RedirectStandardOutput = true }, + out output); diff --git a/build/public-api.cake b/build/public-api.cake new file mode 100644 index 0000000..fd1dfbe --- /dev/null +++ b/build/public-api.cake @@ -0,0 +1,181 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#nullable enable + +// --------------------------------------------------------------------------------------------- +// Public API helpers +// --------------------------------------------------------------------------------------------- + +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using SysFile = System.IO.File; + +/* + * Summary : Specifies the kind of changes public APIs have undergone between an older and a newer version. + * Remarks : The values of this enum are sorted in ascending order of importance, + * so that they may be compared. + */ +enum ApiChangeKind +{ + /* + * Summary : Public APIs have not changed between two versions. + */ + None, + + /* + * Summary : A newer version has only added public APIs with respect to an older version. + */ + Additive, + + /* + * Summary : A newer version's public APIs have undergone breaking changes since an older version was published. + */ + Breaking, +} + +/* + * Summary : Gets the kind of change public APIs underwent, according to the presence of new public APIs + * and/or the removal of existing public APIs in all PublicAPI.Unshipped.txt files + * of the repository. + * Params : context - The Cake context. + * Returns : If at least one public API was removed, ApiChangeKind.Breaking; + * if no public API was removed, but at least one was added, ApiChangeKind.Additive; + * if no public API was removed nor added, ApiChangeKind.None. + */ +static ApiChangeKind GetPublicApiChangeKind(this ICakeContext context) +{ + context.Information("Computing API change kind according to unshipped public API files..."); + var result = ApiChangeKind.None; + foreach (var unshippedPath in context.GetAllPublicApiFilePairs().Select(pair => pair.UnshippedPath)) + { + var fileResult = context.GetPublicApiChangeKind(unshippedPath); + context.Verbose($"{unshippedPath} -> {fileResult}"); + if (fileResult == ApiChangeKind.Breaking) + { + return ApiChangeKind.Breaking; + } + else if (fileResult > result) + { + result = fileResult; + } + } + + return result; +} + +/* + * Summary : Transfers unshipped public API definitions to PublicAPI.Shipped.txt + * in all directories of the repository. + * Params : context - The Cake context. + * Returns : An enumeration of the modified files. + */ +static IEnumerable TransferAllPublicApiToShipped(this ICakeContext context) +{ + context.Information("Updating public API files..."); + foreach (var pair in context.GetAllPublicApiFilePairs()) + { + context.Verbose($"Updating {pair.ShippedPath}..."); + if (context.TransferPublicApiToShipped(pair.UnshippedPath, pair.ShippedPath)) + { + yield return pair.ShippedPath; + yield return pair.UnshippedPath; + } + } +} + +/* + * Summary : Gets all public API definition file pairs in the repository. + * Params : context - The Cake context. + * Returns : An enumeration of (UnshippedPath, ShippedPath) tuples. + */ +static IEnumerable<(FilePath UnshippedPath, FilePath ShippedPath)> GetAllPublicApiFilePairs(this ICakeContext context) +{ + (FilePath UnshippedPath, FilePath ShippedPath)? GetPair(FilePath shippedPath) + { + var unshippedPath = shippedPath.GetDirectory().CombineWithFilePath("PublicAPI.Unshipped.txt"); + return context.FileSystem.Exist(unshippedPath) ? (unshippedPath, shippedPath) : null; + } + + return context + .GetFiles("**/PublicAPI.Shipped.txt", new() { IsCaseSensitive = true }) + .Select(GetPair) + .Where(maybePair => maybePair.HasValue) + .Select(maybePair => maybePair!.Value); +} + +/* + * Summary : Gets the kind of change public APIs underwent, according to the presence of new public APIs + * and/or the removal of existing public APIs. + * Params : context - The Cake context. + * unshippedPath - The FilePath of PublicAPI.Unshipped.txt + * Returns : If at least one public API was removed, ApiChangeKind.Breaking; + * if no public API was removed, but at least one was added, ApiChangeKind.Additive; + * if no public API was removed nor added, ApiChangeKind.None. + */ +static ApiChangeKind GetPublicApiChangeKind(this ICakeContext context, FilePath unshippedPath) +{ + var unshippedLines = SysFile.ReadAllLines(unshippedPath.FullPath, Encoding.UTF8); + static bool IsEmptyOrStartsWithHash(string s) => s.Length == 0 || s[0] == '#'; + var unshippedPublicApiLines = unshippedLines.SkipWhile(IsEmptyOrStartsWithHash); + const string RemovedPrefix = "*REMOVED*"; + var newApiPresent = false; + foreach (var line in unshippedPublicApiLines) + { + if (line.StartsWith(RemovedPrefix, StringComparison.Ordinal)) + { + return ApiChangeKind.Breaking; + } + + newApiPresent = true; + } + + return newApiPresent ? ApiChangeKind.Additive : ApiChangeKind.None; +} + +/* + * Summary : Transfers unshipped public API definitions to PublicAPI.Shipped.txt + * Params : context - The Cake context. + * unshippedPath - The FilePath of PublicAPI.Unshipped.txt + * shippedPath - The FilePath of PublicAPI.Shipped.txt + * Returns : true if files were modified; false otherwise. + */ +static bool TransferPublicApiToShipped(this ICakeContext context, FilePath unshippedPath, FilePath shippedPath) +{ + var utf8 = new UTF8Encoding(false); + var unshippedLines = SysFile.ReadAllLines(unshippedPath.FullPath, utf8); + var unshippedHeaderLines = unshippedLines.TakeWhile(IsEmptyOrStartsWithHash).ToArray(); + if (unshippedHeaderLines.Length == unshippedLines.Length) + { + return false; + } + + static bool IsEmptyOrStartsWithHash(string s) => s.Length == 0 || s[0] == '#'; + var shippedLines = SysFile.ReadAllLines(shippedPath.FullPath, utf8); + var shippedHeaderLines = shippedLines.TakeWhile(IsEmptyOrStartsWithHash).ToArray(); + + const string RemovedPrefix = "*REMOVED*"; + static bool StartsWithRemovedPrefix(string s) => s.StartsWith(RemovedPrefix, StringComparison.Ordinal); + static bool DoesNotStartWithRemovedPrefix(string s) => !StartsWithRemovedPrefix(s); + var removedLines = unshippedLines + .Skip(unshippedHeaderLines.Length) + .Where(StartsWithRemovedPrefix) + .Select(l => l[(RemovedPrefix.Length)..]) + .OrderBy(l => l, StringComparer.Ordinal) // For BinarySearch + .ToArray(); + + bool IsNotRemoved(string s) => Array.BinarySearch(removedLines, s, StringComparer.Ordinal) < 0; + var newShippedLines = shippedLines + .Skip(shippedHeaderLines.Length) + .Where(IsNotRemoved) + .Concat(unshippedLines + .Skip(unshippedHeaderLines.Length) + .Where(DoesNotStartWithRemovedPrefix)) + .OrderBy(l => l, StringComparer.Ordinal); + + SysFile.WriteAllLines(shippedPath.FullPath, shippedHeaderLines.Concat(newShippedLines), utf8); + SysFile.WriteAllLines(unshippedPath.FullPath, unshippedHeaderLines, utf8); + return true; +} diff --git a/build/setup-teardown.cake b/build/setup-teardown.cake new file mode 100644 index 0000000..10edfb4 --- /dev/null +++ b/build/setup-teardown.cake @@ -0,0 +1,33 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#nullable enable + +// ============================================================================================= +// Setup and Teardown, common to all scripts +// ============================================================================================= + +Setup(context => +{ + var data = new BuildData(context); + if (data.IsCI && !data.IsGitHubAction) + { + throw new CakeException(255, "This script can only run locally or in a GitHub Actions workflow."); + } + + return data; +}); + +Teardown((context, data) => +{ + // For some reason, DotNetBuildServerShutdown hangs in a GitHub Actions runner; + // it is still useful on a local machine though + if (!data.IsCI) + { + context.DotNetBuildServerShutdown(new DotNetBuildServerShutdownSettings + { + Razor = true, + VBCSCompiler = true, + }); + } +}); diff --git a/build/versioning.cake b/build/versioning.cake new file mode 100644 index 0000000..521da75 --- /dev/null +++ b/build/versioning.cake @@ -0,0 +1,362 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +// Do not use #addin because the assembly is distributed within Cake.Tool +#r NuGet.Versioning + +#nullable enable + +using NuGet.Versioning; + +// --------------------------------------------------------------------------------------------- +// Version management helpers +// --------------------------------------------------------------------------------------------- + +using System.Diagnostics.CodeAnalysis; +using System.Text.RegularExpressions; + +/* + * Summary : Specifies how to modify the version specification upon publishing a release. + */ +enum VersionSpecChange +{ + /* + * Summary : Do not force a version increment; do not modify the unstable tag. + */ + None, + + /* + * Summary : Do not force a version increment; add an unstable tag if not present. + */ + Unstable, + + /* + * Summary : Do not force a version increment; remove the unstable tag if present. + */ + Stable, + + /* + * Summary : Force a minor version increment with respect to the latest stable version; add an unstable tag. + */ + Minor, + + /* + * Summary : Force a major version increment and minor version reset with respect to the latest stable version; add an unstable tag. + */ + Major, +} + +/* + * Summary : Specifies a kind of version increment. + * Remarks : The values of this enum are sorted in ascending order of importance, + * so that they may be compared. + */ +enum VersionIncrement +{ + /* + * Summary : Represents no version advancement. + */ + None, + + /* + * Summary : Represents the increment of minor version. + */ + Minor, + + /* + * Summary : Represents the increment of major version and reset of minor version. + */ + Major, +} + +/* + * Summary : Represents a Major.Minor[-Tag] version as found in version.json. + */ +sealed record VersionSpec +{ + private static readonly Regex VersionSpecRegex = new Regex( + @"(?-imsx)^v?(?0|[1-9][0-9]*)\.(?0|[1-9][0-9]*)(-(?.*))?$", + RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture); + + private VersionSpec(int major, int minor, string tag) + { + Major = major; + Minor = minor; + Tag = tag; + } + + /* + * Summary : Gets the major version. + */ + public int Major { get; } + + /* + * Summary : Gets the minor version. + */ + public int Minor { get; } + + /* + * Summary : Gets current unstable tag. + * Value : The current unstable tag, or the empty string if the current version is stable. + */ + public string Tag { get; } + + /* + * Summary : Gets a value indicating whether this instance has an unstable tag. + */ + public bool HasTag => !string.IsNullOrEmpty(Tag); + + /* + * Summary : Attempts to parse a VersionSpec from the specified string. + * Params : str - The string to parse. + * result - When this method returns true, the parsed VersionSpec. + * Returns : True is successful; false otherwise. + */ + public static bool TryParse(string str, [MaybeNullWhen(false)] out VersionSpec result) + { + var match = VersionSpecRegex.Match(str); + if (!match.Success) + { + result = null; + return false; + } + + result = new( + int.Parse(match.Groups["major"].Value), + int.Parse(match.Groups["minor"].Value), + match.Groups["tag"].Value + ); + + return true; + } + + public override string ToString() => $"{Major}.{Minor}{(HasTag ? "-" + Tag : null)}"; + + /* + * Summary : Gets an instance of VersionSpec that represents the same version as the current instance + * and has no unstable tag. + * Returns : If this instance has no unstable tag, this instance; otherwise, a newly-constructed VersionSpec + * that represents the same version as the current instance and has no unstable tag. + */ + public VersionSpec Stable() => HasTag ? new(Major, Minor, string.Empty) : this; + + /* + * Summary : Gets an instance of VersionSpec that represents the same version as the current instance + * and has the specified unstable tag. + * Params : tag - The unstable tag of the returned instance. + * Returns : If this instance's Tag property is equal to the given tag, this instance; otherwise, a newly-constructed VersionSpec + * that represents the same version as the current instance and has the specified unstable tag. + */ + public VersionSpec Unstable(string tag) => string.Equals(Tag, tag, StringComparison.Ordinal) ? this : new(Major, Minor, tag); + + /* + * Summary : Gets an instance of VersionSpec that represents the next minor version with respect to the current instance + * and has the specified unstable tag. + * Params : tag - The unstable tag of the returned instance. + * Returns : A newly-constructed VersionSpec. + */ + public VersionSpec NextMinor(string tag) => new(Major, Minor + 1, tag); + + /* + * Summary : Gets an instance of VersionSpec that represents the next major version with respect to the current instance + * and has the specified unstable tag. + * Params : tag - The unstable tag of the returned instance. + * Returns : A newly-constructed VersionSpec. + */ + public VersionSpec NextMajor(string tag) => new(Major + 1, 0, tag); + + /* + * Summary : Gets an instance of VersionSpec that represents the result of applying the specified change + * to the current instance. + * Params : action - An enumeration value representing the kind of change to apply. + * tag - If the returned instance has an unstable tag, the unstable tag of the returned instance; + * otherwise, this parameter is ignored. + * Returns : Result - The result of applying action to the current instance. + * Changed - If Result is equal to the current instance, false; otherwise, true. + */ + public (VersionSpec Result, bool Changed) ApplyChange(VersionSpecChange change, string tag) + => change switch { + VersionSpecChange.Unstable => HasTag ? (this, false) : (Unstable(tag), true), + VersionSpecChange.Stable => HasTag ? (Stable(), true) : (this, false), + VersionSpecChange.Minor => (NextMinor(tag), true), + VersionSpecChange.Major => (NextMajor(tag), true), + _ => (this, false), + }; +} + +/* + * Summary : Represents the version.json file, for the purpose of applying version advances. + */ +sealed class VersionFile +{ + private const string VersionJsonPath = "version.json"; + private const string DefaultFirstUnstableTag = "preview"; + + private readonly JsonNode _json; + + private VersionFile(FilePath path, JsonNode json, VersionSpec versionSpec, string firstUnstableTag) + { + Path = path; + _json = json; + VersionSpec = versionSpec; + FirstUnstableTag = firstUnstableTag; + } + + /* + * Summary : Gets the FilePath of the version.json file. + */ + public FilePath Path { get; } + + /* + * Summary : Gets a VersionSpec representing the "version" value in the version.json file. + */ + public VersionSpec VersionSpec { get; private set; } + + /* + * Summary : Gets the unstable tag to use for version advances. + * Value : Either the "release.firstUnstableTag" value read from version.json, + * or "preview" as a default value. + */ + public string FirstUnstableTag { get; private init; } + + /* + * Summary : Constructs a VersionFile instance by loading the repository's version.json file. + * Returns : A newly-constructed instance of VersionFile, representing the loaded data. + */ + public static VersionFile Load() + { + var path = new FilePath(VersionJsonPath); + var json = LoadJsonObject(path); + var versionStr = GetJsonPropertyValue(json, "version", path + " file"); + Ensure(VersionSpec.TryParse(versionStr, out var versionSpec), $"{VersionJsonPath} contains invalid version specification '{versionStr}'."); + var firstUnstableTag = DefaultFirstUnstableTag; + var release = json["release"]; + if (release is not null) + { + var firstUnstableTagNode = release["firstUnstableTag"]; + if (firstUnstableTagNode is JsonValue firstUnstableTagValue && firstUnstableTagValue.TryGetValue(out var firstUnstableTagStr) && !string.IsNullOrEmpty(firstUnstableTagStr)) + { + firstUnstableTag = firstUnstableTagStr; + } + } + + return new(path, json, versionSpec, firstUnstableTag); + } + + /* + * Summary : Applies a version spec change to this instance. + * Params : context - The Cake context. + * change - An enumeration value representing the kind of change to apply. + * Returns : If the VersionSpec property is actually changed as a result of change, true; otherwise, false. + * Remarks : - This method does not save the modified version.json file; you will have to call the Save method + * if this method returns true. + */ + public bool ApplyVersionSpecChange(ICakeContext context, VersionSpecChange change) + { + var previousVersionSpec = VersionSpec; + (VersionSpec, var changed) = VersionSpec.ApplyChange(change, FirstUnstableTag); + if (changed) + { + context.Information($"Version spec changed from {previousVersionSpec} to {VersionSpec}."); + } + else + { + context.Information("Version spec not changed."); + } + + return changed; + } + + /* + * Summary : Saves the version.json file, possibly with a modified VersionSpec, back to the repository. + */ + public void Save() + { + _json["version"] = JsonValue.Create(VersionSpec.ToString()); + SaveJson(_json, Path); + } +} + +/* + * Summary : Computes the VersionSpecChange to apply upon release. + * Params : context - The Cake context. + * currentVersion - The current version as computed by NBGV + * requestedChange - The version spec change requested by the user + * checkPublicApi - If true, account for changes in public API files. + * Returns : The actual change to apply . + */ +static VersionSpecChange ComputeVersionSpecChange( + this ICakeContext context, + SemanticVersion currentVersion, + VersionSpecChange requestedChange, + bool checkPublicApi) +{ + // Throw if versions are messed up + var (latestVersion, latestStableVersion) = context.GitGetLatestVersions(); + context.Information($"Latest version is {latestVersion?.ToString() ?? "(none)"}"); + context.Information($"Latest stable version is {latestStableVersion?.ToString() ?? "(none)"}"); + Ensure( + VersionComparer.Compare(currentVersion, latestStableVersion, VersionComparison.Version) > 0, + $"Versioning anomaly detected: current version ({currentVersion}) is not higher than than latest stable version ({latestStableVersion?.ToString() ?? "none"})."); + Ensure( + VersionComparer.Compare(currentVersion, latestStableVersion, VersionComparison.Version) > 0, + $"Versioning anomaly detected: latest version ({latestVersion?.ToString() ?? "none"}) is not higher than than latest stable version ({latestStableVersion?.ToString() ?? "none"})."); + Ensure( + VersionComparer.Compare(currentVersion, latestVersion, VersionComparison.Version) > 0, + $"Versioning anomaly detected: current version ({currentVersion}) is not higher than than last stable version ({latestStableVersion?.ToString() ?? "none"})."); + + // Determine how we are currently already incrementing version + var currentVersionIncrement = latestStableVersion == null ? VersionIncrement.Major + : currentVersion.Major > latestStableVersion.Major ? VersionIncrement.Major + : currentVersion.Minor > latestStableVersion.Minor ? VersionIncrement.Minor + : VersionIncrement.None; + context.Information($"Current version increment: {currentVersionIncrement}"); + + // Determine the kind of change in public API + var publicApiChangeKind = checkPublicApi ? context.GetPublicApiChangeKind() : ApiChangeKind.None; + context.Information($"Public API change kind: {publicApiChangeKind}{(checkPublicApi ? null : " (not checked)")}"); + + // Determine the version increment required by SemVer rules + var isInitialDevelopmentPhase = latestStableVersion == null || latestStableVersion.Major == 0; + var semanticVersionIncrement = publicApiChangeKind switch { + ApiChangeKind.Breaking => isInitialDevelopmentPhase ? VersionIncrement.Minor : VersionIncrement.Major, + ApiChangeKind.Additive => isInitialDevelopmentPhase ? VersionIncrement.None : VersionIncrement.Minor, + _ => VersionIncrement.None, + }; + context.Information($"Required version increment according to Semantic Versioning rules: {semanticVersionIncrement}"); + + // Determine the requested version increment, if any. + context.Information($"Requested version spec change: {requestedChange}"); + var requestedVersionIncrement = requestedChange switch { + VersionSpecChange.Major => VersionIncrement.Major, + VersionSpecChange.Minor => VersionIncrement.Minor, + _ => VersionIncrement.None, + }; + context.Information($"Requested version increment: {requestedVersionIncrement}."); + + // Adjust requested version increment to follow SemVer rules + if (semanticVersionIncrement > requestedVersionIncrement) + { + requestedVersionIncrement = semanticVersionIncrement; + } + + // Determine the kind of version increment actually required + var actualVersionIncrement = requestedVersionIncrement > currentVersionIncrement ? requestedVersionIncrement : VersionIncrement.None; + context.Information($"Required version increment with respect to current version: {actualVersionIncrement}"); + + // Determine the actual version spec change to apply: + // - forget any increment-related change (already accounted for via requestedVersionIncrement) + // - set the change to the required increment if any, otherwise leave it as is (None, Unstable, Stable) + var actualChange = requestedChange switch { + VersionSpecChange.Major or VersionSpecChange.Minor => VersionSpecChange.None, + _ => requestedChange, + }; + actualChange = actualVersionIncrement switch { + VersionIncrement.Major => VersionSpecChange.Major, + VersionIncrement.Minor => VersionSpecChange.Minor, + _ => actualChange, + }; + context.Information($"Actual version spec change: {actualChange}."); + + return actualChange; +} diff --git a/build/workspace.cake b/build/workspace.cake new file mode 100644 index 0000000..d0885be --- /dev/null +++ b/build/workspace.cake @@ -0,0 +1,28 @@ +// Copyright (C) Tenacom and contributors. Licensed under the MIT license. +// See LICENSE file in the project root for full license information. + +#nullable enable + +// --------------------------------------------------------------------------------------------- +// Workspace helpers +// --------------------------------------------------------------------------------------------- + +/* + * Summary : Delete all intermediate and output directories. + * On a local machine, also delete Visual Studio and ReSharper caches. + * Params : context - The Cake context. + */ +static void CleanAll(this ICakeContext context, BuildData data) +{ + context.DeleteDirectoryIfExists(".vs"); + context.DeleteDirectoryIfExists("_ReSharper.Caches"); + context.DeleteDirectoryIfExists("artifacts"); + context.DeleteDirectoryIfExists("logs"); + context.DeleteDirectoryIfExists("TestResults"); + foreach (var project in data.Solution.Projects) + { + var projectDirectory = project.Path.GetDirectory(); + context.DeleteDirectoryIfExists(projectDirectory.Combine("bin")); + context.DeleteDirectoryIfExists(projectDirectory.Combine("obj")); + } +} diff --git a/global.json b/global.json index 64c9698..c97c814 100644 --- a/global.json +++ b/global.json @@ -5,7 +5,7 @@ "allowPrerelease": false }, "msbuild-sdks": { - "Buildvana.Sdk": "1.0.0-alpha.20", + "Buildvana.Sdk": "1.0.0-alpha.23", "Microsoft.Build.NoTargets": "3.6.0" } } diff --git a/graphics/PackageIcon.png b/graphics/PackageIcon.png index b05ba4103cd4f01a81c06a71c6e82afb7ca37886..9aa96a51385ca935f8f02ac876ef8fa606fc6218 100644 GIT binary patch literal 44901 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

uv7Y7o9Y1B`v1IaVjr&VTOrO~(tDH;PL5;Cej( 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 literal 46869 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 diff --git a/graphics/README.md b/graphics/README.md new file mode 100644 index 0000000..1212257 --- /dev/null +++ b/graphics/README.md @@ -0,0 +1,49 @@ +# Graphics + +All the graphic elements listed below, except where otherwise specified, are Copyright (C) Tenacom and contributors and are licensed under the MIT license. See the LICENSE file in the project root for full license information. + +## `SquareLogo.svg` + +Reference logo, basic square logo. Used as NuGet package icon, favicon for web-based documentation, and anywhere a square-shaped logo is needed or preferred. + +This is a modifed version of [Peace](#peace). Modified by [@rdeago](https://github.com/rdeago). + +Related files: + +- `PackageIcon.png` (512x512px) + +## `Readme.svg` + +Graphic header for README file. + +Uses the following material: [SquareLogo](#squarelogo); [Repo](#repo). + +Related files: + +- `Readme.png` (720x160px) + +## `SocialCard.svg` + +Social card for GitHub project. + +Uses the following material: [SquareLogo](#squarelogo); [Repo](#repo); [Courier Prime](#courier-prime). + +Related files: + +- `SocialCard.png` (1280x640px) + +## Third-party material + +The following third-party material was used to produce the above files. + +### Peace + +The [Peace](https://thenounproject.com/icon/1951204) vector picture, by AomAm, was obtained from [the Noun Project](https://thenounproject.com/) under the [Creative Commons Attribution 3.0 Unported (CC BY 3.0)](https://creativecommons.org/licenses/by/3.0/) license. + +### Repo + +The [Repo](https://fontlibrary.org/en/font/repo) font, by Stefan Peev, was obtained from [Font Library](https://fontlibrary.org) under the [SIL Open Font License (OFL)](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL). + +### Courier Prime + +The [Courier Prime](https://fontlibrary.org/en/font/courier-prime) font, by Alan Dague-Greene of Quote-Unquote Apps, was obtained from [Font Library](https://fontlibrary.org) under the [SIL Open Font License (OFL)](https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL). diff --git a/graphics/Readme.png b/graphics/Readme.png new file mode 100644 index 0000000000000000000000000000000000000000..b106aba0db694fb51df26ad8405357aa2e3c6c26 GIT binary patch literal 57355 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 GLjDgFpfX + + + + + image/svg+xml + + + + + + + + + Buildvana SDK + + + + + Develop in a state of bliss + diff --git a/graphics/SocialCard.png b/graphics/SocialCard.png new file mode 100644 index 0000000000000000000000000000000000000000..f56c6cef0657cd5ebe7ff400fec31faa7e66f786 GIT binary patch literal 89822 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 + + + + + image/svg+xml + + + + + + + + + + + + + + + + Buildvana SDK + Develop in a state of bliss + + + + + https://github.com/Tenacom/Buildvana.Sdk + diff --git a/graphics/SquareLogo.svg b/graphics/SquareLogo.svg new file mode 100644 index 0000000..e81f68a --- /dev/null +++ b/graphics/SquareLogo.svg @@ -0,0 +1,84 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/nuget.config b/nuget.config index 6c66007..f296ae9 100644 --- a/nuget.config +++ b/nuget.config @@ -1,9 +1,14 @@ + + + + + diff --git a/src/Buildvana.Sdk.SourceGenerators/AdditionalAssemblyInfoGenerator.cs b/src/Buildvana.Sdk.SourceGenerators/AdditionalAssemblyInfoGenerator.cs index 0b9f791..6e1f5aa 100644 --- a/src/Buildvana.Sdk.SourceGenerators/AdditionalAssemblyInfoGenerator.cs +++ b/src/Buildvana.Sdk.SourceGenerators/AdditionalAssemblyInfoGenerator.cs @@ -1,11 +1,5 @@ -// --------------------------------------------------------------------------------------- -// Copyright (C) Riccardo De Agostini and contributors. All rights reserved. -// Licensed under the MIT license. +// Copyright (C) Tenacom and Contributors. Licensed under the MIT license. // See the LICENSE file in the project root for full license information. -// -// Part of this file may be third-party code, distributed under a compatible license. -// See the THIRD-PARTY-NOTICES file in the project root for third-party copyright notices. -// --------------------------------------------------------------------------------------- using System.Text; using Buildvana.Sdk.SourceGenerators.Internal; diff --git a/src/Buildvana.Sdk.SourceGenerators/Internal/AdditionalAssemblyInfoValues.cs b/src/Buildvana.Sdk.SourceGenerators/Internal/AdditionalAssemblyInfoValues.cs index cd3cf67..f034c97 100644 --- a/src/Buildvana.Sdk.SourceGenerators/Internal/AdditionalAssemblyInfoValues.cs +++ b/src/Buildvana.Sdk.SourceGenerators/Internal/AdditionalAssemblyInfoValues.cs @@ -1,11 +1,5 @@ -// --------------------------------------------------------------------------------------- -// Copyright (C) Riccardo De Agostini and contributors. All rights reserved. -// Licensed under the MIT license. +// Copyright (C) Tenacom and Contributors. Licensed under the MIT license. // See the LICENSE file in the project root for full license information. -// -// Part of this file may be third-party code, distributed under a compatible license. -// See the THIRD-PARTY-NOTICES file in the project root for third-party copyright notices. -// --------------------------------------------------------------------------------------- namespace Buildvana.Sdk.SourceGenerators.Internal; diff --git a/src/Buildvana.Sdk.SourceGenerators/Internal/AnalyzerConfigOptionsProviderExtensions.cs b/src/Buildvana.Sdk.SourceGenerators/Internal/AnalyzerConfigOptionsProviderExtensions.cs index facbe41..df81e58 100644 --- a/src/Buildvana.Sdk.SourceGenerators/Internal/AnalyzerConfigOptionsProviderExtensions.cs +++ b/src/Buildvana.Sdk.SourceGenerators/Internal/AnalyzerConfigOptionsProviderExtensions.cs @@ -1,11 +1,5 @@ -// --------------------------------------------------------------------------------------- -// Copyright (C) Riccardo De Agostini and contributors. All rights reserved. -// Licensed under the MIT license. +// Copyright (C) Tenacom and Contributors. Licensed under the MIT license. // See the LICENSE file in the project root for full license information. -// -// Part of this file may be third-party code, distributed under a compatible license. -// See the THIRD-PARTY-NOTICES file in the project root for third-party copyright notices. -// --------------------------------------------------------------------------------------- using System; using Microsoft.CodeAnalysis.Diagnostics; diff --git a/src/Buildvana.Sdk.SourceGenerators/Internal/StringBuilderExtensions.cs b/src/Buildvana.Sdk.SourceGenerators/Internal/StringBuilderExtensions.cs index 860a331..7d6797e 100644 --- a/src/Buildvana.Sdk.SourceGenerators/Internal/StringBuilderExtensions.cs +++ b/src/Buildvana.Sdk.SourceGenerators/Internal/StringBuilderExtensions.cs @@ -1,11 +1,5 @@ -// --------------------------------------------------------------------------------------- -// Copyright (C) Riccardo De Agostini and contributors. All rights reserved. -// Licensed under the MIT license. +// Copyright (C) Tenacom and Contributors. Licensed under the MIT license. // See the LICENSE file in the project root for full license information. -// -// Part of this file may be third-party code, distributed under a compatible license. -// See the THIRD-PARTY-NOTICES file in the project root for third-party copyright notices. -// --------------------------------------------------------------------------------------- using System.Text; using Microsoft.CodeAnalysis; diff --git a/stylecop.json b/stylecop.json index 2ced0f7..f1b4f17 100644 --- a/stylecop.json +++ b/stylecop.json @@ -21,7 +21,7 @@ "namingRules": { "allowCommonHungarianPrefixes": true, - "allowedHungarianPrefixes": [], + "allowedHungarianPrefixes": ["db", "id", "x"], "allowedNamespaceComponents": [], "includeInferredTupleElementNames": false, "tupleElementNameCasing": "PascalCase" @@ -38,13 +38,8 @@ }, "documentationRules": { - "companyName": "Riccardo De Agostini", - "copyrightText": "{decoration}\r\nCopyright (C) {companyName} and contributors. All rights reserved.\nLicensed under the {licenseName} license.\nSee the {licenseFile} file in the project root for full license information.\r\n\r\nPart of this file may be third-party code, distributed under a compatible license.\r\nSee the THIRD-PARTY-NOTICES file in the project root for third-party copyright notices.\r\n{decoration}", - "variables": { - "decoration": "---------------------------------------------------------------------------------------", - "licenseName": "MIT", - "licenseFile": "LICENSE" - }, + "companyName": "Tenacom", + "copyrightText": "Copyright (C) {companyName} and Contributors. Licensed under the MIT license.\r\nSee the LICENSE file in the project root for full license information.", "xmlHeader": false, "documentInterfaces": true, "documentExposedElements": true, diff --git a/version.json b/version.json new file mode 100644 index 0000000..11b4b91 --- /dev/null +++ b/version.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "1.0-preview", + "assemblyVersion": { + "precision": "major" + }, + "nuGetPackageVersion": { + "semVer": 2.0 + }, + "publicReleaseRefSpec": [ + "^refs/heads/main$", + "^refs/heads/v\\d+\\.\\d+$" + ], + "release": { + "firstUnstableTag": "preview" + }, + "pathFilters": [] +}