From ff0487fb79d0e00b448dc9db7409b039edf665fe Mon Sep 17 00:00:00 2001 From: RJ Hollberg Date: Sun, 9 Mar 2025 20:24:37 -0600 Subject: [PATCH 1/9] infra: set up template repo sync workflow --- .github/workflows/template-sync.yml | 82 +++++++++++++++++++++++++++++ README.md | 8 +++ 2 files changed, 90 insertions(+) create mode 100644 .github/workflows/template-sync.yml diff --git a/.github/workflows/template-sync.yml b/.github/workflows/template-sync.yml new file mode 100644 index 0000000..cac08d1 --- /dev/null +++ b/.github/workflows/template-sync.yml @@ -0,0 +1,82 @@ +name: Template Sync + +on: + # Runs daily at midnight (https://crontab.guru/#0_0_1_*_*) + # schedule: + # - cron: "0 0 1 * *" + + # Can be triggered manually + workflow_dispatch: + +env: + # Configurable parameters + GIT_USERNAME: github-actions + GIT_EMAIL: github-actions@github.com + TEMPLATE_REPO_URL: https://github.com/TaffarelJr/.github.git + TEMPLATE_REPO_NAME: template + TEMPLATE_REPO_BRANCH: main + BASE_BRANCH_NAME: main + SYNC_BRANCH_NAME: template-sync + +jobs: + template-sync: + name: Sync with Template Repo + runs-on: ubuntu-latest + + # https://docs.github.com/en/actions/using-jobs/assigning-permissions-to-jobs + permissions: + contents: write # Needed to push changes + pull-requests: write # Needed to create PRs + + steps: + - name: Checkout repo + uses: actions/checkout@v4 + with: + fetch-depth: 0 # Ensure full history for merging + + - name: Configure Git + run: | + git config user.name "${{ env.GIT_USERNAME }}" + git config user.email "${{ env.GIT_EMAIL }}" + + - name: Get latest changes from template + run: | + git remote add ${{ env.TEMPLATE_REPO_NAME }} ${{ env.TEMPLATE_REPO_URL }} || true + git fetch ${{ env.TEMPLATE_REPO_NAME }} + + - name: Check for changes to sync + id: check_changes + run: git diff --quiet origin/${{ env.BASE_BRANCH_NAME }} ${{ env.TEMPLATE_REPO_NAME }}/${{ env.TEMPLATE_REPO_BRANCH }} || echo "has_changes=true" >> $GITHUB_OUTPUT + + - name: Switch to new branch + if: steps.check_changes.outputs.has_changes == 'true' + run: git checkout -B ${{ env.SYNC_BRANCH_NAME }} origin/${{ env.BASE_BRANCH_NAME }} + + - name: Merge branches + if: steps.check_changes.outputs.has_changes == 'true' + id: merge + run: | + if git merge --no-edit ${{ env.TEMPLATE_REPO_NAME }}/${{ env.TEMPLATE_REPO_BRANCH }}; then + echo "conflict=false" >> $GITHUB_OUTPUT + else + echo "conflict=true" >> $GITHUB_OUTPUT + echo "Merge conflicts detected. These will need to be resolved manually." + fi + + - name: Push changes + if: steps.check_changes.outputs.has_changes == 'true' + run: git push --force origin ${{ env.SYNC_BRANCH_NAME }} + + - name: Create or update PR + if: steps.check_changes.outputs.has_changes == 'true' + uses: peter-evans/create-pull-request@v7 + with: + branch: ${{ env.SYNC_BRANCH_NAME }} + base: ${{ env.BASE_BRANCH_NAME }} + title: "${{ steps.merge.outputs.conflict == 'true' && 'NEEDS RESOLUTION: ' || '' }}Merge changes from template repo" + body: > + Automated sync from template repo. + + ${{ steps.merge.outputs.conflict == 'true' && '⚠️ **This PR contains merge conflicts that need to be resolved manually before merging.**' || '' }} + labels: "${{ steps.merge.outputs.conflict == 'true' && 'template sync,needs resolution' || 'template sync' }}" + delete-branch: true diff --git a/README.md b/README.md index fe3dd20..0de2b34 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ flowchart TB - [Description of Files in This Template Repo](#description-of-files-in-this-template-repo) - [Community Health Files](#community-health-files) - [GitHub Templates](#github-templates) + - [GitHub Workflows](#github-workflows) - [Other Files](#other-files) ## Description of Files in This Template Repo @@ -101,6 +102,12 @@ flowchart TB | 📄[Issue template chooser][chooser] | ✅ | | | | 📄[Pull request template][prs] | | ✅ | | +### [GitHub Workflows][workflows] + +| Workflow | Exists only
in this repo | Synced to
(and overridden in)
derived repos | Description | +| :---------------------- | :--------------------------: | :-------------------------------------------------: | :------------------------------------------------------------------ | +| 📄[Template Sync][sync] | | ✅ | Synchronizes changes
from a template repo
to a derived repo | + ### Other Files | File | Exists only
in this repo | Synced to
(and overridden in)
derived repos | Purpose | @@ -131,6 +138,7 @@ flowchart TB [security]: ./SECURITY.md [styleGuides]: ./docs/StyleGuides.md [support]: ./SUPPORT.md +[sync]: ./.github/workflows/template-sync.yml [vsCode]: ./.vscode/ From ffd57c12e8535a51ad0961035fcba892af968b17 Mon Sep 17 00:00:00 2001 From: RJ Hollberg Date: Mon, 10 Mar 2025 12:32:42 -0600 Subject: [PATCH 2/9] infra: define GitHub repo settings --- .github/settings.yml | 302 +++++++++++++++++++++++++++++++++++++++++++ README.md | 3 + 2 files changed, 305 insertions(+) create mode 100644 .github/settings.yml diff --git a/.github/settings.yml b/.github/settings.yml new file mode 100644 index 0000000..44a64f5 --- /dev/null +++ b/.github/settings.yml @@ -0,0 +1,302 @@ +repository: + + #───────────────────────────────────────────────────────────────────────────── + # "About" section (on Home Page) + # https://github.com/repository-settings/app/blob/master/docs/plugins/repository.md + # https://docs.github.com/en/rest/repos/repos#update-a-repository + #───────────────────────────────────────────────────────────────────────────── + + # A short description of the repo + # MUST BE A SINGLE LINE + description: Special base template repo that contains shared files + + # A URL with more information about the repo + homepage: https://github.com/TaffarelJr + + # A comma-separated list of topics to set on the repo + # See https://github.com/topics + topics: community-health, github, github-config, github-profile, template-repo + + #───────────────────────────────────────────────────────────────────────────── + # Settings → General + # https://github.com/repository-settings/app/blob/master/docs/plugins/repository.md + # https://docs.github.com/en/rest/repos/repos#update-a-repository + #───────────────────────────────────────────────────────────────────────────── + + # The name of the repo + name: .github + + # Whether the repo is available as a template + is_template: true + + # Whether to require contributors to sign off on web-based commits + web_commit_signoff_required: false + + # The default branch for the repo + # NOTE: The new branch must already exist before changing this value! + default_branch: main + + # Whether downloads are enabled for this repo + # Hidden. Deprecated in 2012, but property still exists + has_downloads: true + + # Whether the wiki is enabled for this repo + has_wiki: true + + # Whether issues are enabled for this repo + has_issues: true + + # Whether private forks are allowed for this repo + # Hidden. Personal, public repos are always fork-able + allow_forking: true + + # Whether discussions are enabled for this repo + has_discussions: true + + # Whether projects are enabled for this repo + has_projects: true + + # Whether to allow merging pull requests with a merge commit + allow_merge_commit: false + + # Default value for a merge commit title (PR_TITLE|MERGE_MESSAGE) + merge_commit_title: MERGE_MESSAGE + + # Default value for a merge commit message (PR_TITLE|PR_BODY|BLANK) + merge_commit_message: PR_TITLE + + # Whether to allow squash-merging pull requests + allow_squash_merge: false + + # Default value for a squash merge commit title (PR_TITLE|COMMIT_OR_PR_TITLE) + squash_merge_commit_title: COMMIT_OR_PR_TITLE + + # Default value for a squash merge commit message (PR_BODY|COMMIT_MESSAGES|BLANK) + squash_merge_commit_message: COMMIT_MESSAGES + + # Whether to allow rebase-merging pull requests + allow_rebase_merge: true + + # Whether to always allow a pull request head branch + # that is behind its base branch to be updated + # even if it is not required to be up-to-date before merging + allow_update_branch: true + + # Whether to allow auto-merge on pull requests + allow_auto_merge: false + + # Whether to allow automatically deleting head branches + # when pull requests are merged + delete_branch_on_merge: true + + # The visibility of the repo (public|private) + visibility: public + + # Whether to archive this repo + # ('false' will unarchive a previously archived repo) + archived: false + +#─────────────────────────────────────────────────────────────────────────────── +# Settings → Collaborators +# https://github.com/repository-settings/app/blob/master/docs/plugins/collaborators.md +# https://docs.github.com/en/rest/collaborators/collaborators +#─────────────────────────────────────────────────────────────────────────────── +collaborators: + +#─────────────────────────────────────────────────────────────────────────────── +# Settings → Branches +# https://github.com/repository-settings/app/blob/master/docs/plugins/branches.md +# https://docs.github.com/en/rest/branches/branch-protection +#─────────────────────────────────────────────────────────────────────────────── +branches: + + # This section is being deprecated in favor of rulesets (below) + +#─────────────────────────────────────────────────────────────────────────────── +# Settings → Rules → Rulesets +# https://github.com/repository-settings/app/blob/master/docs/plugins/rulesets.md +# https://docs.github.com/en/rest/repos/rules#update-a-repository-ruleset +# https://github.com/github/ruleset-recipes +#─────────────────────────────────────────────────────────────────────────────── +rulesets: + + - name: Protect default branch history + target: branch + enforcement: disabled + bypass_actors: [] + conditions: + ref_name: + include: [~DEFAULT_BRANCH] + exclude: [] + rules: + - type: deletion + - type: non_fast_forward + + - name: PRs must be reviewed + target: branch + enforcement: disabled + bypass_actors: [] + conditions: + ref_name: + include: [~DEFAULT_BRANCH] + exclude: [] + rules: + - type: pull_request + parameters: + required_approving_review_count: 1 + dismiss_stale_reviews_on_push: true + require_code_owner_review: true + require_last_push_approval: false + required_review_thread_resolution: true + automatic_copilot_code_review_enabled: true + + - name: Status checks must pass + target: branch + enforcement: disabled + bypass_actors: + - actor_id: 5 # Repository admin + actor_type: RepositoryRole + bypass_mode: pull_request + conditions: + ref_name: + include: [~DEFAULT_BRANCH] + exclude: [] + rules: + - type: required_status_checks + parameters: + strict_required_status_checks_policy: true + do_not_enforce_on_create: true + required_status_checks: + - context: Analyze (actions) + integration_id: 15368 # GitHub Actions + - type: code_scanning + parameters: + code_scanning_tools: + - tool: CodeQL + security_alerts_threshold: high_or_higher + alerts_threshold: errors + + - name: Protect version tags + target: tag + enforcement: active + bypass_actors: [] + conditions: + ref_name: + include: [refs/tags/v*] + exclude: [] + rules: + - type: deletion + - type: non_fast_forward + +#─────────────────────────────────────────────────────────────────────────────── +# Issues → Labels +# https://github.com/repository-settings/app/blob/master/docs/plugins/labels.md +#─────────────────────────────────────────────────────────────────────────────── +labels: + + # Built-in, default labels + # (leave colors and descriptions set to default values) + + - name: bug + color: "#d73a4a" + description: Something isn't working + + - name: documentation + color: "#0075ca" + description: Improvements or additions to documentation + + - name: duplicate + color: "#cfd3d7" + description: This issue or pull request already exists + + - name: enhancement + color: "#a2eeef" + description: New feature or request + + - name: good first issue + color: "#7057ff" + description: Good for newcomers + + - name: help wanted + color: "#008672" + description: Extra attention is needed + + - name: invalid + color: "#e4e669" + description: This doesn't seem right + + - name: needs repro + color: "#d97b0b" + description: Missing replication steps + + - name: question + color: "#d876e3" + description: Further information is requested + + - name: wont fix + color: "#ffffff" + description: This will not be worked on + + # Additional, custom labels + + - name: critical + color: "#1a0000" + description: Highest priority + + - name: dependencies + color: "#1267d3" + description: Updates to dependencies + + - name: needs fix + color: "#ffa366" + description: Looking for a solution + + - name: performance + color: "#0e8a16" + description: Performance issue or regression + + # GitHub Actions Workflows + + - name: template sync + color: "#006b75" + description: Changes replicated from template repo + + # Dependabot Ecosystems + # https://docs.github.com/en/code-security/dependabot/ecosystems-supported-by-dependabot/supported-ecosystems-and-repositories + # (each uses its own marketing color) + + # - name: .NET SDK + # color: "#522ed1" + # description: Updates to the required .NET SDK + + # - name: Dev Containers + # color: "#2753e3" + # description: Updates to Dev Container Features + + # - name: Docker + # color: "#2465ea" + # description: Updates to Docker image tags in a Kubernetes manifest + + # - name: Docker Compose + # color: "#2465ea" + # description: Updates to Docker image tags in a Compose file + + # - name: Git submodule + # color: "#ee4f39" + # description: Updates to Git submodules + + - name: GitHub Actions + color: "#000000" + description: Updates to GitHub Actions + + # - name: npm + # color: "#cb0817" + # description: Updates to npm packages + + # - name: NuGet + # color: "#07497f" + # description: Updates to NuGet packages + + # - name: Terraform + # color: "#7b43ba" + # description: Updates to Terraform modules diff --git a/README.md b/README.md index 0de2b34..3b30145 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,7 @@ flowchart TB | 📄[`.gitmessage`][message] | | ✅ | [Commit message template][messageGuide] | | 📄[`copilot-instructions.md`][copilot] | | ✅ | [Copilot configuration][copilotDoc] | | 📄[`dependabot.yml`][dependabot] | | ✅ | [Dependabot configuration][dependabotDoc] | +| 📄[`settings.yml`][settings] | | ✅ | [Repo configuration][settingsDoc] | @@ -136,6 +137,7 @@ flowchart TB [messageGuide]: ./docs/StyleGuides.md#commit-messages [prs]: ./.github/pull_request_template.md [security]: ./SECURITY.md +[settings]: ./.github/settings.yml [styleGuides]: ./docs/StyleGuides.md [support]: ./SUPPORT.md [sync]: ./.github/workflows/template-sync.yml @@ -147,5 +149,6 @@ flowchart TB [dependabotDoc]: https://docs.github.com/en/code-security/dependabot/working-with-dependabot/dependabot-options-reference [freeCodeCamp]: https://www.freecodecamp.org/news/how-to-use-the-dot-github-repository [health]: https://docs.github.com/en/communities/setting-up-your-project-for-healthy-contributions/creating-a-default-community-health-file +[settingsDoc]: https://github.com/repository-settings/app [templates]: https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository [workflows]: https://docs.github.com/en/actions/how-tos/writing-workflows From ef31d1e4a48a5bfd67fd4a907f07e346f293fd36 Mon Sep 17 00:00:00 2001 From: RJ Hollberg Date: Fri, 27 Jun 2025 19:15:18 -0600 Subject: [PATCH 3/9] docs: add new template repo checklist --- README.md | 2 + _Checklist.md | 178 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 _Checklist.md diff --git a/README.md b/README.md index 3b30145..cc632d0 100644 --- a/README.md +++ b/README.md @@ -114,6 +114,7 @@ flowchart TB | :------------------------------------- | :--------------------------: | :-------------------------------------------------: | :------------------------------------------ | | 📁[`.vscode/`][vsCode] | | ✅ | Contains VSCode settings | | 📁[`docs/`][docs] | ✅ | | Contains documentation | +| 📄[`_Checklist.md`][checklist] | | ✅ | New repo checklist | | 📄[`.editorconfig`][editorConfig] | | ✅ | [Style guide rule definitions][styleGuides] | | 📄[`.gitmessage`][message] | | ✅ | [Commit message template][messageGuide] | | 📄[`copilot-instructions.md`][copilot] | | ✅ | [Copilot configuration][copilotDoc] | @@ -122,6 +123,7 @@ flowchart TB +[checklist]: ./_Checklist.md [chooser]: ./.github/ISSUE_TEMPLATE/config.yml [coc]: ./CODE_OF_CONDUCT.md [codeOwners]: ./.github/CODEOWNERS diff --git a/_Checklist.md b/_Checklist.md new file mode 100644 index 0000000..b218dee --- /dev/null +++ b/_Checklist.md @@ -0,0 +1,178 @@ +# Creating a New Template Repo + +Template repos use the [`.github`][template] repo +as their base template. +Follow these steps to create a new repo derived from it. + +#### Table of Contents + +- [1. Create the new template repo](#1-create-the-new-template-repo) +- [2. Configure manual repo settings](#2-configure-manual-repo-settings) +- [3. Clone the repo](#3-clone-the-repo) +- [4. Customize template files](#4-customize-template-files) +- [5. Customize root repo files](#5-customize-root-repo-files) +- [6. Override repo settings](#6-override-repo-settings) +- [7. Push the changes to GitHub](#7-push-the-changes-to-github) +- [8. Run the template sync](#8-run-the-template-sync) + +## 1. Create the new template repo + +- DO NOT use a template in GitHub when creating the new repo; + we'll use Git-merge to get the necessary files instead. +- The new repo name should use the format: `.template-` + - For example: `.template-NuGet` +- Leave the description blank. +- Don't add any files to the new repo, leave it empty. + +## 2. Configure manual repo settings + +Not all repo settings can be managed from the `settings.yml` file. +The following settings must be configured manually: + +- Go to `Settings` + - Go to `General` + - Check `Limit how many branches and tags can be updated in a single push` + - Up to `2` branches and tags can be updated in a push + - Go to `Moderation options` + - Go to `Code review limits` + - Check `Limit to users explicitly granted read or higher access` + - Go to `Actions` + - Go to `General` + - Check `Allow GitHub Actions to create and approve pull requests` + - Click `Save` + - Go to `Advanced Security` + - Enable `Private vulnerability reporting` + - Enable `Dependency graph` _(if necessary)_ + - Enable `Grouped security updates` + - Set up `CodeQL analysis` to use `Default` settings + - Go to `Secrets and variables` + - Go to `Actions` + - Add a repository secret for `CODECOV_TOKEN` + (global upload token value can be found on the Codecov website, + either in repo settings or profile settings) + +## 3. Clone the repo + +Clone the repo locally and open it in Visual Studio Code. +The [`.github`][template] repo needs to be added as an upstream remote +so the template sync can import the commits to the new repo +with those in the [`.github`][template] repo. +Execute the following commands: + +```bash +# May need to configure SSH key +git config remote.pushdefault origin +git remote add template git@github.com:TaffarelJr/.github.git +git fetch template +git checkout -B main template/main +git config commit.template .gitmessage +``` + +## 4. Customize template files + +Some files that were synced from the [`.github`][template] repo +need to be customized for this new template repo. + +- Delete the following files that will + reside only in the [`.github`][template] repo: + - `.github/ISSUE_TEMPLATE/config.yml` + - `.github/FUNDING.yml` + - `CODE_OF_CONDUCT.md` +- Find all instances of `TaffarelJr/.github` in the repo + - Replace them with `TaffarelJr/` in **ONLY** these files: + - `CONTRIBUTING.md` + - `SECURITY.md` + - `SUPPORT.md` + - `/ISSUE_TEMPLATE/01_bug_report.yml` + - `/ISSUE_TEMPLATE/02_performance_issue.yml` + - `/ISSUE_TEMPLATE/03_feature_request.yml` +- Un-comment the cron schedule in the [`template-sync`][sync] workflow. +- Make any additional changes to the template files as necessary. +- Commit the changes with the message: `chore: customize template files` + +## 5. Customize root repo files + +Now we can add deeper customization to the root repo files +to meet the needs of the new template: + +- Replace the contents of the `_Checklist.md` file + - Back up the previous file while you finish working through it +- Modify `.editorconfig` as needed +- Generate a `.gitattributes` file using https://github.com/gitattributes/gitattributes +- Generate a `.gitignore` file using https://github.com/github/gitignore +- Replace the contents of the `README.md` file +- Add any additional ecosystems to `dependabot.yml` +- Make any additional changes to the root files as necessary. +- Commit the changes with the message: `chore: customize root files` + +## 6. Override repo settings + +Most of the settings in the `settings.yml` file +are appropriate to inherit from the [`.github`][template] repo. +Only a few of them need to be overridden in the new template repo. + +Replace the contents of the file with the following, +filling in the values as indicated: + +```yaml +_extends: .github + +repository: + + #───────────────────────────────────────────────────────────────────────────── + # "About" section (on Home Page) + # https://github.com/repository-settings/app/blob/master/docs/plugins/repository.md + # https://docs.github.com/en/rest/repos/repos#update-a-repository + #───────────────────────────────────────────────────────────────────────────── + + # A short description of the repo + # MUST BE A SINGLE LINE + description: <1-line description>. + + # A URL with more information about the repo + homepage: + + # A comma-separated list of topics to set on the repo + # See https://github.com/topics + topics: , , ... + + #───────────────────────────────────────────────────────────────────────────── + # Settings → General + # https://github.com/repository-settings/app/blob/master/docs/plugins/repository.md + # https://docs.github.com/en/rest/repos/repos#update-a-repository + #───────────────────────────────────────────────────────────────────────────── + + # The name of the repo + name: + + # Whether to allow merging pull requests with a merge commit + allow_merge_commit: false +``` + +Make any additional changes as needed. +Commit the changes with the message: `chore: customize repo settings` + +## 7. Push the changes to GitHub + +Push the branch to GitHub: + +```bash +git push +``` + +The settings should take effect almost immediately; +verify that the repo description and tags appear on the home page. + +## 8. Run the template sync + +Finally, validate the template sync. +To do this, go to `Actions` → `Template Sync` → `Run workflow` → `main` +and click `Run workflow`. The process should complete with no changes. + + + +[sync]: .github/workflows/template-sync.yml + + + +[template]: https://github.com/TaffarelJr/.github From 4d2751f4d483a508ce6656ce14e9841d55602439 Mon Sep 17 00:00:00 2001 From: RJ Hollberg Date: Mon, 30 Jun 2025 17:50:56 -0600 Subject: [PATCH 4/9] chore: customize template files --- .github/FUNDING.yml | 6 - .github/ISSUE_TEMPLATE/01_bug_report.yml | 10 +- .../ISSUE_TEMPLATE/02_performance_issue.yml | 10 +- .github/ISSUE_TEMPLATE/03_feature_request.yml | 10 +- .github/ISSUE_TEMPLATE/config.yml | 5 - CODE_OF_CONDUCT.md | 153 ------------------ CONTRIBUTING.md | 12 +- SECURITY.md | 2 +- SUPPORT.md | 62 ++++++- 9 files changed, 81 insertions(+), 189 deletions(-) delete mode 100644 .github/FUNDING.yml delete mode 100644 .github/ISSUE_TEMPLATE/config.yml delete mode 100644 CODE_OF_CONDUCT.md diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index 225c6b4..0000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1,6 +0,0 @@ -# This file configures the "Sponsor" button in the repo. -# Please see the documentation for all configuration options: -# https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/displaying-a-sponsor-button-in-your-repository - -buy_me_a_coffee: TaffarelJr -thanks_dev: u/gh/TaffarelJr diff --git a/.github/ISSUE_TEMPLATE/01_bug_report.yml b/.github/ISSUE_TEMPLATE/01_bug_report.yml index 0ad1776..d113ab5 100644 --- a/.github/ISSUE_TEMPLATE/01_bug_report.yml +++ b/.github/ISSUE_TEMPLATE/01_bug_report.yml @@ -7,7 +7,7 @@ body: attributes: value: > Thanks for helping to fix something that's broken! 🤗 See the - [`CONTRIBUTING.md`](https://github.com/TaffarelJr/.github/blob/main/CONTRIBUTING.md#how-do-i-submit-a-good-bug-report) + [`CONTRIBUTING.md`](https://github.com/TaffarelJr/.template-NuGet/blob/main/CONTRIBUTING.md#how-do-i-submit-a-good-bug-report) file for tips on writing an effective bug report. - type: checkboxes @@ -19,19 +19,19 @@ body: options: - label: > I've searched the - [Documentation](https://github.com/TaffarelJr/.github/tree/main/docs) - and [Wiki](https://github.com/TaffarelJr/.github/wiki) + [Documentation](https://github.com/TaffarelJr/.template-NuGet/tree/main/docs) + and [Wiki](https://github.com/TaffarelJr/.template-NuGet/wiki) for information on this topic, and I'm sure it's a bug. required: true - label: > I've searched and/or posted in the - [Discussions](https://github.com/TaffarelJr/.github/discussions) + [Discussions](https://github.com/TaffarelJr/.template-NuGet/discussions) about this bug. required: true - label: > I've searched the existing - [Issues](https://github.com/TaffarelJr/.github/issues) + [Issues](https://github.com/TaffarelJr/.template-NuGet/issues) and this bug has not been reported yet. required: true diff --git a/.github/ISSUE_TEMPLATE/02_performance_issue.yml b/.github/ISSUE_TEMPLATE/02_performance_issue.yml index eae6216..0b121bf 100644 --- a/.github/ISSUE_TEMPLATE/02_performance_issue.yml +++ b/.github/ISSUE_TEMPLATE/02_performance_issue.yml @@ -7,7 +7,7 @@ body: attributes: value: > Thanks for helping us make our code faster! 🤗 See the - [`CONTRIBUTING.md`](https://github.com/TaffarelJr/.github/blob/main/CONTRIBUTING.md#how-do-i-submit-a-good-bug-report) + [`CONTRIBUTING.md`](https://github.com/TaffarelJr/.template-NuGet/blob/main/CONTRIBUTING.md#how-do-i-submit-a-good-bug-report) file for tips on writing an effective performance issue. - type: checkboxes @@ -19,19 +19,19 @@ body: options: - label: > I've searched the - [Documentation](https://github.com/TaffarelJr/.github/tree/main/docs) - and [Wiki](https://github.com/TaffarelJr/.github/wiki) + [Documentation](https://github.com/TaffarelJr/.template-NuGet/tree/main/docs) + and [Wiki](https://github.com/TaffarelJr/.template-NuGet/wiki) for information on this topic, and I'm sure it's not performing the way it should. required: true - label: > I've searched and/or posted in the - [Discussions](https://github.com/TaffarelJr/.github/discussions) + [Discussions](https://github.com/TaffarelJr/.template-NuGet/discussions) about this problem. required: true - label: > I've searched the existing - [Issues](https://github.com/TaffarelJr/.github/issues) + [Issues](https://github.com/TaffarelJr/.template-NuGet/issues) and this problem has not been reported yet. required: true diff --git a/.github/ISSUE_TEMPLATE/03_feature_request.yml b/.github/ISSUE_TEMPLATE/03_feature_request.yml index 37d4b1c..67b8093 100644 --- a/.github/ISSUE_TEMPLATE/03_feature_request.yml +++ b/.github/ISSUE_TEMPLATE/03_feature_request.yml @@ -7,7 +7,7 @@ body: attributes: value: > Thanks for helping us add more value! 🤗 See the - [`CONTRIBUTING.md`](https://github.com/TaffarelJr/.github/blob/main/CONTRIBUTING.md#how-do-i-submit-a-good-enhancement-suggestion) + [`CONTRIBUTING.md`](https://github.com/TaffarelJr/.template-NuGet/blob/main/CONTRIBUTING.md#how-do-i-submit-a-good-enhancement-suggestion) file for tips on writing an effective enhancement suggestion. - type: checkboxes @@ -19,14 +19,14 @@ body: options: - label: > I've searched the - [Documentation](https://github.com/TaffarelJr/.github/tree/main/docs) - and [Wiki](https://github.com/TaffarelJr/.github/wiki) + [Documentation](https://github.com/TaffarelJr/.template-NuGet/tree/main/docs) + and [Wiki](https://github.com/TaffarelJr/.template-NuGet/wiki) for information on this topic, and I'm sure it's not currently available. required: true - label: > I've searched and/or posted in the - [Discussions](https://github.com/TaffarelJr/.github/discussions) + [Discussions](https://github.com/TaffarelJr/.template-NuGet/discussions) about this enhancement. required: true - label: > @@ -36,7 +36,7 @@ body: required: true - label: > I've searched the existing - [Issues](https://github.com/TaffarelJr/.github/issues) + [Issues](https://github.com/TaffarelJr/.template-NuGet/issues) and this enhancement has not been suggested yet. required: true diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 37e8a76..0000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,5 +0,0 @@ -blank_issues_enabled: true -contact_links: - - name: Community Discussions - url: https://github.com/TaffarelJr/.github/discussions - about: Please ask and answer questions here. diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index 5ddf39d..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,153 +0,0 @@ -# Contributor Covenant Code of Conduct - -While these are my personal projects, -I welcome contributors who share my passion for clean code and creative solutions. -This Code of Conduct is here to ensure we maintain a -respectful and positive environment for anyone who wants to join in. -Think of it as the "house rules" that help us collaborate effectively -and have fun while building cool stuff together. -I've kept a standard format that's commonly used in other public repos (below); -but essentially it says: treat others with respect, -be constructive in your feedback, -and remember we're all here because we love coding -and want to make awesome things together! - -#### Table of Contents - -- [Our Pledge](#our-pledge) -- [Our Standards](#our-standards) -- [Enforcement Responsibilities](#enforcement-responsibilities) -- [Scope](#scope) -- [Enforcement](#enforcement) -- [Enforcement Guidelines](#enforcement-guidelines) - - [1. Correction](#1-correction) - - [2. Warning](#2-warning) - - [3. Temporary Ban](#3-temporary-ban) - - [4. Permanent Ban](#4-permanent-ban) -- [Attribution](#attribution) - -## Our Pledge - -We as members, contributors, and leaders pledge to make participation in our -community a harassment-free experience for everyone, regardless of age, body -size, visible or invisible disability, ethnicity, sex characteristics, gender -identity and expression, level of experience, education, socio-economic status, -nationality, personal appearance, race, caste, color, religion, or sexual -identity and orientation. - -We pledge to act and interact in ways that contribute to an open, welcoming, -diverse, inclusive, and healthy community. - -## Our Standards - -Examples of behavior that contributes to a positive environment for our -community include: - -- Demonstrating empathy and kindness toward other people -- Being respectful of differing opinions, viewpoints, and experiences -- Giving and gracefully accepting constructive feedback -- Accepting responsibility and apologizing to those affected by our mistakes, - and learning from the experience -- Focusing on what is best not just for us as individuals, but for the overall - community - -Examples of unacceptable behavior include: - -- The use of sexualized language or imagery, and sexual attention or advances of - any kind -- Trolling, insulting or derogatory comments, and personal or political attacks -- Public or private harassment -- Publishing others' private information, such as a physical or email address, - without their explicit permission -- Other conduct which could reasonably be considered inappropriate in a - professional setting - -## Enforcement Responsibilities - -Community leaders are responsible for clarifying and enforcing our standards of -acceptable behavior and will take appropriate and fair corrective action in -response to any behavior that they deem inappropriate, threatening, offensive, -or harmful. - -Community leaders have the right and responsibility to remove, edit, or reject -comments, commits, code, wiki edits, issues, and other contributions that are -not aligned to this Code of Conduct, and will communicate reasons for moderation -decisions when appropriate. - -## Scope - -This Code of Conduct applies within all community spaces, and also applies when -an individual is officially representing the community in public spaces. -Examples of representing our community include using an official email address, -posting via an official social media account, or acting as an appointed -representative at an online or offline event. - -## Enforcement - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported to the community leaders responsible for enforcement at -[INSERT CONTACT METHOD]. -All complaints will be reviewed and investigated promptly and fairly. - -All community leaders are obligated to respect the privacy and security of the -reporter of any incident. - -## Enforcement Guidelines - -Community leaders will follow these Community Impact Guidelines in determining -the consequences for any action they deem in violation of this Code of Conduct: - -### 1. Correction - -**Community Impact**: Use of inappropriate language or other behavior deemed -unprofessional or unwelcome in the community. - -**Consequence**: A private, written warning from community leaders, providing -clarity around the nature of the violation and an explanation of why the -behavior was inappropriate. A public apology may be requested. - -### 2. Warning - -**Community Impact**: A violation through a single incident or series of -actions. - -**Consequence**: A warning with consequences for continued behavior. No -interaction with the people involved, including unsolicited interaction with -those enforcing the Code of Conduct, for a specified period of time. This -includes avoiding interactions in community spaces as well as external channels -like social media. Violating these terms may lead to a temporary or permanent -ban. - -### 3. Temporary Ban - -**Community Impact**: A serious violation of community standards, including -sustained inappropriate behavior. - -**Consequence**: A temporary ban from any sort of interaction or public -communication with the community for a specified period of time. No public or -private interaction with the people involved, including unsolicited interaction -with those enforcing the Code of Conduct, is allowed during this period. -Violating these terms may lead to a permanent ban. - -### 4. Permanent Ban - -**Community Impact**: Demonstrating a pattern of violation of community -standards, including sustained inappropriate behavior, harassment of an -individual, or aggression toward or disparagement of classes of individuals. - -**Consequence**: A permanent ban from any sort of public interaction within the -community. - -## Attribution - -This Code of Conduct is adapted from the -[Contributor Covenant](https://www.contributor-covenant.org/), version 2.1, -available at -. - -Community Impact Guidelines were inspired by -[Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/inclusion). - -For answers to common questions about this code of conduct, see the FAQ at -. Translations are available at -. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d71e26d..99f9abe 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -269,12 +269,12 @@ This guide is based on the [contributing.md][contrib] website. -[discussions]: https://github.com/TaffarelJr/.github/discussions -[issues]: https://github.com/TaffarelJr/.github/issues -[newBug]: https://github.com/TaffarelJr/.github/issues/new?template=01_bug_report.yml -[newFeature]: https://github.com/TaffarelJr/.github/issues/new?template=03_feature_request.yml -[newIssue]: https://github.com/TaffarelJr/.github/issues/new?template=02_performance_issue.yml -[wiki]: https://github.com/TaffarelJr/.github/wiki +[discussions]: https://github.com/TaffarelJr/.template-NuGet/discussions +[issues]: https://github.com/TaffarelJr/.template-NuGet/issues +[newBug]: https://github.com/TaffarelJr/.template-NuGet/issues/new?template=01_bug_report.yml +[newFeature]: https://github.com/TaffarelJr/.template-NuGet/issues/new?template=03_feature_request.yml +[newIssue]: https://github.com/TaffarelJr/.template-NuGet/issues/new?template=02_performance_issue.yml +[wiki]: https://github.com/TaffarelJr/.template-NuGet/wiki diff --git a/SECURITY.md b/SECURITY.md index a7e577d..cc1a791 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -12,4 +12,4 @@ and may ask for additional information or guidance. -[advisories]: https://github.com/TaffarelJr/.github/security/advisories +[advisories]: https://github.com/TaffarelJr/.template-NuGet/security/advisories diff --git a/SUPPORT.md b/SUPPORT.md index e39e2b6..d670553 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -40,6 +40,56 @@ Here are some tips: See [`CONTRIBUTING.md`][contrib] on how to contribute. +## Supported Platforms + +This project aims to support a wide range of .NET platforms for compatibility. +To this end, we support platforms that implement .NET Standard 2.0 or higher. +However, we **highly recommend** using _only_ the platforms that are +officially supported by Microsoft. + +- 🟢 = Fully supported. +- 🟡 = Still works, but upgrading is highly recommended. +- 🔴 = Not supported. _(security vulnerabilities, lack of tool support, etc.)_ + +| Platform | End of
Microsoft Support | .NET Standard
2.0 | .NET Standard
2.1 | +| :------------------- | ---------------------------: | :-------------------: | :-------------------: | +| .NET 9 _(STS)_ | May 12, 2026 | 🟢 | 🟢 | +| .NET 8 _(LTS)_ | November 10, 2026 | 🟢 | 🟢 | +| .NET 7 _(STS)_ | May 14, 2024 | 🟡 | 🟡 | +| .NET 6 _(LTS)_ | November 12, 2024 | 🟡 | 🟡 | +| .NET 5 _(STS)_ | May 10, 2022 | 🟡 | 🟡 | +| .NET Core 3.1 | December 13, 2022 | 🟡 | 🟡 | +| .NET Core 3.0 | March 3, 2020 | 🔴 | 🔴 | +| .NET Core 2.2 | December 23, 2019 | 🔴 | — | +| .NET Core 2.1 | August 21, 2021 | 🔴 | — | +| .NET Core 2.0 | October 1, 2018 | 🔴 | — | +| .NET Core 1.1 | June 27, 2019 | — | — | +| .NET Core 1.0 | June 27, 2019 | — | — | +| .NET Framework 4.8.1 | _\_ | 🟢 | — | +| .NET Framework 4.8 | _\_ | 🟢 | — | +| .NET Framework 4.7.2 | _\_ | 🟢 | — | +| .NET Framework 4.7.1 | _\_ | 🟢 | — | +| .NET Framework 4.7 | _\_ | 🟢 | — | +| .NET Framework 4.6.2 | January 12, 2027 | 🟢 | — | +| .NET Framework 4.6.1 | Apr 26, 2022 | 🔴 | — | +| .NET Framework 4.6 | Apr 26, 2022 | — | — | +| .NET Framework 4.5.2 | Apr 26, 2022 | — | — | +| .NET Framework 4.5.1 | Jan 12, 2016 | — | — | +| .NET Framework 4.5 | Jan 12, 2016 | — | — | + +> [!NOTE] +> .NET Framework 4.6.2 and later are supported as long as they're on a supported +> Windows OS. + +More information about supported platforms can be found here: + +- [.NET Core & .NET][netCore] support policies +- [.NET Standard][netStandard] implementation +- [.NET Framework][netFramework] support policies +- [Microsoft Product & Service Lifecycle information][winLifecycle] (search page) + - [Windows 10 Home and Pro][winHomePro] release support + - [Windows Server][winServer] release support + ## Attribution This document was shamelessly stolen and modified @@ -53,13 +103,19 @@ from the [Remark][remark] repo. -[discussions]: https://github.com/TaffarelJr/.github/discussions -[issues]: https://github.com/TaffarelJr/.github/issues -[wiki]: https://github.com/TaffarelJr/.github/wiki +[discussions]: https://github.com/TaffarelJr/.template-NuGet/discussions +[issues]: https://github.com/TaffarelJr/.template-NuGet/issues +[wiki]: https://github.com/TaffarelJr/.template-NuGet/wiki +[netCore]: https://dotnet.microsoft.com/platform/support/policy/dotnet-core +[netFramework]: https://docs.microsoft.com/en-us/lifecycle/products/microsoft-net-framework +[netStandard]: https://docs.microsoft.com/en-us/dotnet/standard/net-standard [remark]: https://github.com/remarkjs/.github/blob/main/support.md [rubberduck]: https://rubberduckdebugging.com [sandbox]: https://codesandbox.io +[winHomePro]: https://docs.microsoft.com/en-us/lifecycle/products/windows-10-home-and-pro +[winLifecycle]: https://docs.microsoft.com/en-us/lifecycle/products +[winServer]: https://docs.microsoft.com/en-us/lifecycle/products/windows-server [xy]: https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem/66378#66378 From f9b3ef040aae3b61b3c56ede38ee89c642c995bf Mon Sep 17 00:00:00 2001 From: RJ Hollberg Date: Wed, 2 Jul 2025 10:58:15 -0600 Subject: [PATCH 5/9] chore: customize root files --- .config/dotnet-tools.json | 21 ++ .editorconfig | 239 ++++++++++++++- .gitattributes | 219 ++++++++++++++ .github/dependabot.yml | 26 ++ .gitignore | 613 ++++++++++++++++++++++++++++++++++++++ .vsconfig | 30 ++ StyleCop.json | 68 +++++ global.json | 6 + nuget.config | 18 ++ 9 files changed, 1239 insertions(+), 1 deletion(-) create mode 100644 .config/dotnet-tools.json create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 .vsconfig create mode 100644 StyleCop.json create mode 100644 global.json create mode 100644 nuget.config diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 0000000..a56873e --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,21 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "dotnet-reportgenerator-globaltool": { + "version": "5.4.8", + "commands": ["reportgenerator"], + "rollForward": false + }, + "gitreleasemanager.tool": { + "version": "0.20.0", + "commands": ["dotnet-gitreleasemanager"], + "rollForward": false + }, + "gitversion.tool": { + "version": "6.3.0", + "commands": ["dotnet-gitversion"], + "rollForward": false + } + } +} diff --git a/.editorconfig b/.editorconfig index 4981ab1..5a63bb9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -29,14 +29,251 @@ guidelines = 80 1px solid 5000ff00, 100 1px solid 75ffff00, 120 1px solid ff8b00 # Exceptions required by file format #─────────────────────────────────────────────────────────────────────────────── +[*.{bash,sh}] +end_of_line = lf + [*.md] indent_size = 2 tab_width = 2 +[*.sln] +indent_style = tab + #─────────────────────────────────────────────────────────────────────────────── # Exceptions for structured data files (looks better) #─────────────────────────────────────────────────────────────────────────────── -[*.{json,yaml,yml}] +# JSON configuration files +[*.{json,vsconfig}] +indent_size = 2 +tab_width = 2 + +# XML project files +[*.{csproj,dbproj,fsproj,njsproj,proj,pyproj,rproj,shproj,sqlproj,vbproj,vcproj,vcxitems,vcxproj,wixproj}] +indent_size = 2 +tab_width = 2 + +# XML configuration files +[*.{config,nuspec,projitems,props,resx,ruleset,runsettings,svg,targets,vcxproj.filters,vsct,vsixmanifest,xml}] indent_size = 2 tab_width = 2 + +# YAML configuration files +[*.{yaml,yml}] +indent_size = 2 +tab_width = 2 + +#─────────────────────────────────────────────────────────────────────────────── +# .NET Coding Conventions +#─────────────────────────────────────────────────────────────────────────────── + +[*.cs] + +# Organize usings +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = true +file_header_template = unset + +# this. and Me. preferences +dotnet_style_qualification_for_event = false:silent +dotnet_style_qualification_for_field = false:silent +dotnet_style_qualification_for_method = false:silent +dotnet_style_qualification_for_property = false:silent + +# Language keywords vs BCL types preferences +dotnet_style_predefined_type_for_locals_parameters_members = true:silent +dotnet_style_predefined_type_for_member_access = true:silent + +# Parentheses preferences +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent +dotnet_style_parentheses_in_other_operators = always_for_clarity:silent +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent + +# Modifier preferences +dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent + +# Expression-level preferences +dotnet_style_coalesce_expression = true:suggestion +dotnet_style_collection_initializer = true:suggestion +dotnet_style_explicit_tuple_names = true:suggestion +dotnet_style_null_propagation = true:suggestion +dotnet_style_object_initializer = true:suggestion +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true:silent +dotnet_style_prefer_compound_assignment = true:suggestion +dotnet_style_prefer_conditional_expression_over_assignment = true:silent +dotnet_style_prefer_conditional_expression_over_return = true:silent +dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion +dotnet_style_prefer_inferred_tuple_names = true:suggestion +dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion +dotnet_style_prefer_simplified_boolean_expressions = true:suggestion +dotnet_style_prefer_simplified_interpolation = true:suggestion +# dotnet_style_prefer_collection_expression = true:suggestion + +# Field preferences +dotnet_style_readonly_field = true:suggestion + +# Parameter preferences +dotnet_code_quality_unused_parameters = all:suggestion + +#─────────────────────────────────────────────────────────────────────────────── +# C# Coding Conventions +#─────────────────────────────────────────────────────────────────────────────── + +# var preferences +csharp_style_var_elsewhere = true:silent +csharp_style_var_for_built_in_types = true:silent +csharp_style_var_when_type_is_apparent = true:silent + +# Expression-bodied members +csharp_style_expression_bodied_accessors = true:silent +csharp_style_expression_bodied_constructors = false:silent +csharp_style_expression_bodied_indexers = true:silent +csharp_style_expression_bodied_lambdas = true:silent +csharp_style_expression_bodied_local_functions = false:silent +csharp_style_expression_bodied_methods = true:silent +csharp_style_expression_bodied_operators = true:silent +csharp_style_expression_bodied_properties = true:silent + +# Pattern matching preferences +csharp_style_pattern_matching_over_as_with_null_check = true:suggestion +csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion +csharp_style_prefer_switch_expression = true:suggestion + +# Null-checking preferences +csharp_style_conditional_delegate_call = true:suggestion + +# Modifier preferences +csharp_prefer_static_local_function = true:suggestion +csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async:silent + +# Code-block preferences +csharp_prefer_braces = when_multiline:silent +csharp_prefer_simple_using_statement = true:suggestion + +# Expression-level preferences +csharp_prefer_simple_default_expression = true:suggestion +csharp_style_deconstructed_variable_declaration = true:suggestion +csharp_style_inlined_variable_declaration = true:suggestion +csharp_style_pattern_local_over_anonymous_function = true:suggestion +csharp_style_prefer_index_operator = true:suggestion +csharp_style_prefer_range_operator = true:suggestion +csharp_style_throw_expression = true:suggestion +csharp_style_unused_value_assignment_preference = discard_variable:suggestion +csharp_style_unused_value_expression_statement_preference = discard_variable:silent + +# 'using' directive preferences +csharp_using_directive_placement = outside_namespace:silent + +# Namespace preferences +csharp_style_namespace_declarations = file_scoped + +#─────────────────────────────────────────────────────────────────────────────── +# C# Formatting +#─────────────────────────────────────────────────────────────────────────────── + +# New line preferences +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# Indentation preferences +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = true +csharp_indent_labels = flush_left +csharp_indent_switch_labels = true + +# Space preferences +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = false +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# Wrapping preferences +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = false + +#─────────────────────────────────────────────────────────────────────────────── +# .NET Naming Conventions +#─────────────────────────────────────────────────────────────────────────────── + +# Naming rules + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +# Symbol specifications + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +# Naming styles + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +#─────────────────────────────────────────────────────────────────────────────── +# Code Analysis Exceptions +#─────────────────────────────────────────────────────────────────────────────── + +# CodeAnalysis rules +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ +dotnet_diagnostic.CA1515.severity = none # Consider making public types internal + +# StyleCop rules +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/tree/master/documentation +dotnet_diagnostic.SA1101.severity = none # Prefix local calls with 'this' +dotnet_diagnostic.SA1309.severity = none # Field names must not begin with underscore +dotnet_diagnostic.SA1503.severity = none # Braces must not be omitted +dotnet_diagnostic.SA1600.severity = warning # Elements should be documented +dotnet_diagnostic.SA1633.severity = none # File must have header diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..0c637c9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,219 @@ +#─────────────────────────────────────────────────────────────────────────────── +# Common +# https://github.com/gitattributes/gitattributes/blob/master/Common.gitattributes +#─────────────────────────────────────────────────────────────────────────────── + +# Common settings that generally should always be used with your language specific settings + +# Auto detect text files and perform LF normalization +* text=auto + +# +# The above will handle all files NOT found below +# + +# Documents +*.bibtex text diff=bibtex +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain +*.md text diff=markdown +*.mdx text diff=markdown +*.tex text diff=tex +*.adoc text +*.textile text +*.mustache text +*.csv text eol=crlf +*.tab text +*.tsv text +*.txt text +*.sql text +*.epub diff=astextplain + +# Graphics +*.png binary +*.jpg binary +*.jpeg binary +*.gif binary +*.tif binary +*.tiff binary +*.ico binary +# SVG treated as text by default. +*.svg text +# If you want to treat it as binary, +# use the following line instead. +# *.svg binary +*.eps binary + +# Scripts +*.bash text eol=lf +*.fish text eol=lf +*.ksh text eol=lf +*.sh text eol=lf +*.zsh text eol=lf +# These are explicitly windows files and should use crlf +*.bat text eol=crlf +*.cmd text eol=crlf +*.ps1 text eol=crlf + +# Serialisation +*.json text +*.toml text +*.xml text +*.yaml text +*.yml text + +# Archives +*.7z binary +*.bz binary +*.bz2 binary +*.bzip2 binary +*.gz binary +*.lz binary +*.lzma binary +*.rar binary +*.tar binary +*.taz binary +*.tbz binary +*.tbz2 binary +*.tgz binary +*.tlz binary +*.txz binary +*.xz binary +*.Z binary +*.zip binary +*.zst binary + +# Text files where line endings should be preserved +*.patch -text + +# +# Exclude files from exporting +# + +.gitattributes export-ignore +.gitignore export-ignore +.gitkeep export-ignore + +#─────────────────────────────────────────────────────────────────────────────── +# CSharp +# https://github.com/gitattributes/gitattributes/blob/master/CSharp.gitattributes +#─────────────────────────────────────────────────────────────────────────────── + +# Auto detect text files and perform LF normalization +* text=auto + +*.cs text diff=csharp +*.cshtml text diff=html +*.csx text diff=csharp +*.sln text eol=crlf +*.csproj text eol=crlf + +#─────────────────────────────────────────────────────────────────────────────── +# Dev Container +# https://github.com/gitattributes/gitattributes/blob/master/Global/DevContainer.gitattributes +#─────────────────────────────────────────────────────────────────────────────── + +# Fix syntax highlighting on GitHub to allow comments +.devcontainer.json linguist-language=JSON-with-Comments +devcontainer.json linguist-language=JSON-with-Comments + +#─────────────────────────────────────────────────────────────────────────────── +# Markdown +# https://github.com/gitattributes/gitattributes/blob/master/Markdown.gitattributes +#─────────────────────────────────────────────────────────────────────────────── + +# Apply override to all files in the directory +*.md linguist-detectable + +#─────────────────────────────────────────────────────────────────────────────── +# PowerShell +# https://github.com/gitattributes/gitattributes/blob/master/PowerShell.gitattributes +#─────────────────────────────────────────────────────────────────────────────── + +# Basic .gitattributes for a PowerShell repo. + +# Source files +# ============ +*.ps1 text eol=crlf +*.ps1x text eol=crlf +*.psm1 text eol=crlf +*.psd1 text eol=crlf +*.ps1xml text eol=crlf +*.pssc text eol=crlf +*.psrc text eol=crlf +*.cdxml text eol=crlf + +#─────────────────────────────────────────────────────────────────────────────── +# Visual Studio +# https://github.com/gitattributes/gitattributes/blob/master/Global/VisualStudio.gitattributes +#─────────────────────────────────────────────────────────────────────────────── + +############################################################################### +# Set default behavior to automatically normalize line endings. +############################################################################### +* text=auto + +############################################################################### +# Set the merge driver for project and solution files +# +# Merging from the command prompt will add diff markers to the files if there +# are conflicts (Merging from VS is not affected by the settings below, in VS +# the diff markers are never inserted). Diff markers may cause the following +# file extensions to fail to load in VS. An alternative would be to treat +# these files as binary and thus will always conflict and require user +# intervention with every merge. To do so, just comment the entries below and +# uncomment the group further below +############################################################################### + +*.sln text eol=crlf +*.csproj text eol=crlf +*.vbproj text eol=crlf +*.vcxproj text eol=crlf +*.vcproj text eol=crlf +*.dbproj text eol=crlf +*.fsproj text eol=crlf +*.lsproj text eol=crlf +*.wixproj text eol=crlf +*.modelproj text eol=crlf +*.sqlproj text eol=crlf +*.wwaproj text eol=crlf + +*.xproj text eol=crlf +*.props text eol=crlf +*.filters text eol=crlf +*.vcxitems text eol=crlf + + +#*.sln merge=binary +#*.csproj merge=binary +#*.vbproj merge=binary +#*.vcxproj merge=binary +#*.vcproj merge=binary +#*.dbproj merge=binary +#*.fsproj merge=binary +#*.lsproj merge=binary +#*.wixproj merge=binary +#*.modelproj merge=binary +#*.sqlproj merge=binary +#*.wwaproj merge=binary + +#*.xproj merge=binary +#*.props merge=binary +#*.filters merge=binary +#*.vcxitems merge=binary + +#─────────────────────────────────────────────────────────────────────────────── +# Visual Studio Code +# https://github.com/gitattributes/gitattributes/blob/master/Global/VisualStudioCode.gitattributes +#─────────────────────────────────────────────────────────────────────────────── + +# Fix syntax highlighting on GitHub to allow comments +.vscode/*.json linguist-language=JSON-with-Comments diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6dddb42..d0ecf55 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,6 +7,32 @@ version: 2 updates: + #───────────────────────────────────────────────────────────────────────────── + # Update .NET dependencies + #───────────────────────────────────────────────────────────────────────────── + + - package-ecosystem: dotnet-sdk + directory: / + schedule: + interval: monthly + commit-message: + prefix: chore + labels: [dependencies, .NET SDK] + ignore: + - dependency-name: "*" + update-types: [version-update:semver-patch] + + - package-ecosystem: nuget + directory: / + schedule: + interval: weekly + day: monday + commit-message: + prefix: chore + labels: [dependencies, NuGet] + allow: + - dependency-type: direct + #───────────────────────────────────────────────────────────────────────────── # Update GitHub Actions workflows #───────────────────────────────────────────────────────────────────────────── diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c88b1da --- /dev/null +++ b/.gitignore @@ -0,0 +1,613 @@ +#─────────────────────────────────────────────────────────────────────────────── +# Diff +# https://github.com/github/gitignore/blob/main/Global/Diff.gitignore +#─────────────────────────────────────────────────────────────────────────────── + +*.patch +*.diff + +#─────────────────────────────────────────────────────────────────────────────── +# Dotnet +# https://github.com/github/gitignore/blob/main/Dotnet.gitignore +#─────────────────────────────────────────────────────────────────────────────── + +# Superceded by Visual Studio (below) + +#─────────────────────────────────────────────────────────────────────────────── +# Dotnet Core +# https://github.com/github/gitignore/blob/main/community/DotNet/core.gitignore +#─────────────────────────────────────────────────────────────────────────────── + +# Superceded by Visual Studio (below) + +#─────────────────────────────────────────────────────────────────────────────── +# JetBrains +# https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +#─────────────────────────────────────────────────────────────────────────────── + +# Covers JetBrains IDEs: IntelliJ, GoLand, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# SonarLint plugin +.idea/sonarlint/ +.idea/sonarlint.xml # see https://community.sonarsource.com/t/is-the-file-idea-idea-idea-sonarlint-xml-intended-to-be-under-source-control/121119 + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based HTTP Client +.idea/httpRequests +http-client.private.env.json + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +# Apifox Helper cache +.idea/.cache/.Apifox_Helper +.idea/ApifoxUploaderProjectSetting.xml + +#─────────────────────────────────────────────────────────────────────────────── +# macOS +# https://github.com/github/gitignore/blob/main/Global/macOS.gitignore +#─────────────────────────────────────────────────────────────────────────────── + +# General +.DS_Store +.AppleDouble +.LSOverride +Icon[] + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +#─────────────────────────────────────────────────────────────────────────────── +# TortoiseGit +# https://github.com/github/gitignore/blob/main/Global/TortoiseGit.gitignore +#─────────────────────────────────────────────────────────────────────────────── + +# Project-level settings +/.tgitconfig + +#─────────────────────────────────────────────────────────────────────────────── +# Visual Studio +# https://github.com/github/gitignore/blob/main/VisualStudio.gitignore +#─────────────────────────────────────────────────────────────────────────────── + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates +*.env + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +[Aa][Rr][Mm]64[Ee][Cc]/ +bld/ +[Oo]bj/ +[Oo]ut/ +[Ll]og/ +[Ll]ogs/ + +# Build results on 'Bin' directories +**/[Bb]in/* +# Uncomment if you have tasks that rely on *.refresh files to move binaries +# (https://github.com/github/gitignore/pull/3736) +#!**/[Bb]in/*.refresh + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* +*.trx + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Approval Tests result files +*.received.* + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.idb +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +# but not Directory.Build.rsp, as it configures directory-level build defaults +!Directory.Build.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +**/.paket/paket.exe +paket-files/ + +# FAKE - F# Make +**/.fake/ + +# CodeRush personal settings +**/.cr/personal + +# Python Tools for Visual Studio (PTVS) +**/__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +#tools/** +#!tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog +MSBuild_Logs/ + +# AWS SAM Build and Temporary Artifacts folder +.aws-sam + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +**/.mfractor/ + +# Local History for Visual Studio +**/.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +**/.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets + +# Local History for Visual Studio Code +.history/ + +# Built Visual Studio Code Extensions +*.vsix + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +#─────────────────────────────────────────────────────────────────────────────── +# Visual Studio Code +# https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore +#─────────────────────────────────────────────────────────────────────────────── + +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +!.vscode/*.code-snippets +!*.code-workspace + +# Built Visual Studio Code Extensions +*.vsix + +#─────────────────────────────────────────────────────────────────────────────── +# Windows +# https://github.com/github/gitignore/blob/main/Global/Windows.gitignore +#─────────────────────────────────────────────────────────────────────────────── + +# Windows thumbnail cache files +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk diff --git a/.vsconfig b/.vsconfig new file mode 100644 index 0000000..2e7eee9 --- /dev/null +++ b/.vsconfig @@ -0,0 +1,30 @@ +{ + "version": "1.0", + "components": [ + // Workloads often contain components we don't need. + // For this reason, specify individual components + // and just group by workload. + + // Microsoft.VisualStudio.Workload.CoreEditor + // https://learn.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-community?view=vs-2022#visual-studio-core-editor-included-with-visual-studio-community-2022 + "Microsoft.VisualStudio.Component.CoreEditor", + + // Microsoft.VisualStudio.Workload.ManagedDesktop + // https://learn.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-community?view=vs-2022#net-desktop-development + "Microsoft.Component.MSBuild", + "Microsoft.NetCore.Component.DevelopmentTools", + "Microsoft.NetCore.Component.Runtime.8.0", + "Microsoft.NetCore.Component.Runtime.9.0", + "Microsoft.NetCore.Component.SDK", + "Microsoft.VisualStudio.Component.Debugger.JustInTime", + "Microsoft.VisualStudio.Component.DiagnosticTools", + "Microsoft.VisualStudio.Component.IntelliCode", + "Microsoft.VisualStudio.Component.NuGet", + "Microsoft.VisualStudio.Component.Roslyn.Compiler", + "Microsoft.VisualStudio.Component.Roslyn.LanguageServices", + "Microsoft.VisualStudio.Component.TextTemplating" + ], + "extensions": [ + "https://marketplace.visualstudio.com/items?itemName=PaulHarrington.EditorGuidelines" + ] +} diff --git a/StyleCop.json b/StyleCop.json new file mode 100644 index 0000000..52304c3 --- /dev/null +++ b/StyleCop.json @@ -0,0 +1,68 @@ +{ + "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json", + "settings": { + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/Configuration.md#documentation-rules + "documentationRules": { + "companyName": "RJ Hollberg", + "copyrightText": "Copyright © {companyName}. All rights reserved.\nLicensed under the {licenseName} license.\nSee the {licenseFile} file in the project root for full license information.", + "xmlHeader": true, + "variables": { + "licenseName": "MIT", + "licenseFile": "LICENSE" + }, + "headerDecoration": "─────────────────────────────────────────────────────────────────────────────", + "documentInterfaces": true, + "documentExposedElements": true, + "documentInternalElements": true, + "documentPrivateElements": false, + "documentPrivateFields": false, + "documentationCulture": "en-US", + "fileNamingConvention": "stylecop", + "excludeFromPunctuationCheck": ["seealso"] + }, + + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/Configuration.md#indentation + "indentation": { + "indentationSize": 4, + "tabSize": 4, + "useTabs": false + }, + + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/Configuration.md#layout-rules + "layoutRules": { + "newlineAtEndOfFile": "require", + "allowConsecutiveUsings": true, + "allowDoWhileOnClosingBrace": false + }, + + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/Configuration.md#maintainability-rules + "maintainabilityRules": { + "topLevelTypes": ["class", "interface", "struct", "enum"] + }, + + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/Configuration.md#naming-rules + "namingRules": { + "allowCommonHungarianPrefixes": false, + "allowedHungarianPrefixes": [], + "allowedNamespaceComponents": [], + "includeInferredTupleElementNames": false, + "tupleElementNameCasing": "PascalCase" + }, + + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/Configuration.md#ordering-rules + "orderingRules": { + "elementOrder": ["kind", "accessibility", "constant", "static", "readonly"], + "systemUsingDirectivesFirst": true, + "usingDirectivesPlacement": "outsideNamespace", + "blankLinesBetweenUsingGroups": "allow" + }, + + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/Configuration.md#readability-rules + "readabilityRules": { + "allowBuiltInTypeAliases": false + }, + + // https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/Configuration.md#spacing-rules + "spacingRules": {} + } +} diff --git a/global.json b/global.json new file mode 100644 index 0000000..cdbb589 --- /dev/null +++ b/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "9.0.100", + "rollForward": "latestFeature" + } +} diff --git a/nuget.config b/nuget.config new file mode 100644 index 0000000..51bf47b --- /dev/null +++ b/nuget.config @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + From 599700802e9cb7203bb30c6a8cb31a7662d8fc7e Mon Sep 17 00:00:00 2001 From: RJ Hollberg Date: Fri, 18 Jul 2025 09:55:15 -0600 Subject: [PATCH 6/9] chore: customize repo settings --- .github/settings.yml | 253 ++++--------------------------------------- 1 file changed, 20 insertions(+), 233 deletions(-) diff --git a/.github/settings.yml b/.github/settings.yml index 44a64f5..0336955 100644 --- a/.github/settings.yml +++ b/.github/settings.yml @@ -1,3 +1,5 @@ +_extends: .github + repository: #───────────────────────────────────────────────────────────────────────────── @@ -8,14 +10,14 @@ repository: # A short description of the repo # MUST BE A SINGLE LINE - description: Special base template repo that contains shared files + description: Template repo for publishing NuGet packages # A URL with more information about the repo - homepage: https://github.com/TaffarelJr + homepage: # A comma-separated list of topics to set on the repo # See https://github.com/topics - topics: community-health, github, github-config, github-profile, template-repo + topics: dotnet, csharp, nuget, template-repo #───────────────────────────────────────────────────────────────────────────── # Settings → General @@ -24,93 +26,7 @@ repository: #───────────────────────────────────────────────────────────────────────────── # The name of the repo - name: .github - - # Whether the repo is available as a template - is_template: true - - # Whether to require contributors to sign off on web-based commits - web_commit_signoff_required: false - - # The default branch for the repo - # NOTE: The new branch must already exist before changing this value! - default_branch: main - - # Whether downloads are enabled for this repo - # Hidden. Deprecated in 2012, but property still exists - has_downloads: true - - # Whether the wiki is enabled for this repo - has_wiki: true - - # Whether issues are enabled for this repo - has_issues: true - - # Whether private forks are allowed for this repo - # Hidden. Personal, public repos are always fork-able - allow_forking: true - - # Whether discussions are enabled for this repo - has_discussions: true - - # Whether projects are enabled for this repo - has_projects: true - - # Whether to allow merging pull requests with a merge commit - allow_merge_commit: false - - # Default value for a merge commit title (PR_TITLE|MERGE_MESSAGE) - merge_commit_title: MERGE_MESSAGE - - # Default value for a merge commit message (PR_TITLE|PR_BODY|BLANK) - merge_commit_message: PR_TITLE - - # Whether to allow squash-merging pull requests - allow_squash_merge: false - - # Default value for a squash merge commit title (PR_TITLE|COMMIT_OR_PR_TITLE) - squash_merge_commit_title: COMMIT_OR_PR_TITLE - - # Default value for a squash merge commit message (PR_BODY|COMMIT_MESSAGES|BLANK) - squash_merge_commit_message: COMMIT_MESSAGES - - # Whether to allow rebase-merging pull requests - allow_rebase_merge: true - - # Whether to always allow a pull request head branch - # that is behind its base branch to be updated - # even if it is not required to be up-to-date before merging - allow_update_branch: true - - # Whether to allow auto-merge on pull requests - allow_auto_merge: false - - # Whether to allow automatically deleting head branches - # when pull requests are merged - delete_branch_on_merge: true - - # The visibility of the repo (public|private) - visibility: public - - # Whether to archive this repo - # ('false' will unarchive a previously archived repo) - archived: false - -#─────────────────────────────────────────────────────────────────────────────── -# Settings → Collaborators -# https://github.com/repository-settings/app/blob/master/docs/plugins/collaborators.md -# https://docs.github.com/en/rest/collaborators/collaborators -#─────────────────────────────────────────────────────────────────────────────── -collaborators: - -#─────────────────────────────────────────────────────────────────────────────── -# Settings → Branches -# https://github.com/repository-settings/app/blob/master/docs/plugins/branches.md -# https://docs.github.com/en/rest/branches/branch-protection -#─────────────────────────────────────────────────────────────────────────────── -branches: - - # This section is being deprecated in favor of rulesets (below) + name: .template-NuGet #─────────────────────────────────────────────────────────────────────────────── # Settings → Rules → Rulesets @@ -120,36 +36,6 @@ branches: #─────────────────────────────────────────────────────────────────────────────── rulesets: - - name: Protect default branch history - target: branch - enforcement: disabled - bypass_actors: [] - conditions: - ref_name: - include: [~DEFAULT_BRANCH] - exclude: [] - rules: - - type: deletion - - type: non_fast_forward - - - name: PRs must be reviewed - target: branch - enforcement: disabled - bypass_actors: [] - conditions: - ref_name: - include: [~DEFAULT_BRANCH] - exclude: [] - rules: - - type: pull_request - parameters: - required_approving_review_count: 1 - dismiss_stale_reviews_on_push: true - require_code_owner_review: true - require_last_push_approval: false - required_review_thread_resolution: true - automatic_copilot_code_review_enabled: true - - name: Status checks must pass target: branch enforcement: disabled @@ -169,6 +55,14 @@ rulesets: required_status_checks: - context: Analyze (actions) integration_id: 15368 # GitHub Actions + - context: Analyze (csharp) + integration_id: 15368 # GitHub Actions + - context: Build and Test + integration_id: 15368 # GitHub Actions + - context: codecov/patch + integration_id: 254 # Codecov + - context: codecov/project + integration_id: 254 # Codecov - type: code_scanning parameters: code_scanning_tools: @@ -176,127 +70,20 @@ rulesets: security_alerts_threshold: high_or_higher alerts_threshold: errors - - name: Protect version tags - target: tag - enforcement: active - bypass_actors: [] - conditions: - ref_name: - include: [refs/tags/v*] - exclude: [] - rules: - - type: deletion - - type: non_fast_forward - #─────────────────────────────────────────────────────────────────────────────── # Issues → Labels # https://github.com/repository-settings/app/blob/master/docs/plugins/labels.md #─────────────────────────────────────────────────────────────────────────────── labels: - # Built-in, default labels - # (leave colors and descriptions set to default values) - - - name: bug - color: "#d73a4a" - description: Something isn't working - - - name: documentation - color: "#0075ca" - description: Improvements or additions to documentation - - - name: duplicate - color: "#cfd3d7" - description: This issue or pull request already exists - - - name: enhancement - color: "#a2eeef" - description: New feature or request - - - name: good first issue - color: "#7057ff" - description: Good for newcomers - - - name: help wanted - color: "#008672" - description: Extra attention is needed - - - name: invalid - color: "#e4e669" - description: This doesn't seem right - - - name: needs repro - color: "#d97b0b" - description: Missing replication steps - - - name: question - color: "#d876e3" - description: Further information is requested - - - name: wont fix - color: "#ffffff" - description: This will not be worked on - - # Additional, custom labels - - - name: critical - color: "#1a0000" - description: Highest priority - - - name: dependencies - color: "#1267d3" - description: Updates to dependencies - - - name: needs fix - color: "#ffa366" - description: Looking for a solution - - - name: performance - color: "#0e8a16" - description: Performance issue or regression - - # GitHub Actions Workflows - - - name: template sync - color: "#006b75" - description: Changes replicated from template repo - # Dependabot Ecosystems # https://docs.github.com/en/code-security/dependabot/ecosystems-supported-by-dependabot/supported-ecosystems-and-repositories # (each uses its own marketing color) - # - name: .NET SDK - # color: "#522ed1" - # description: Updates to the required .NET SDK - - # - name: Dev Containers - # color: "#2753e3" - # description: Updates to Dev Container Features - - # - name: Docker - # color: "#2465ea" - # description: Updates to Docker image tags in a Kubernetes manifest - - # - name: Docker Compose - # color: "#2465ea" - # description: Updates to Docker image tags in a Compose file - - # - name: Git submodule - # color: "#ee4f39" - # description: Updates to Git submodules - - - name: GitHub Actions - color: "#000000" - description: Updates to GitHub Actions - - # - name: npm - # color: "#cb0817" - # description: Updates to npm packages - - # - name: NuGet - # color: "#07497f" - # description: Updates to NuGet packages + - name: .NET SDK + color: "#522ed1" + description: Updates to the required .NET SDK - # - name: Terraform - # color: "#7b43ba" - # description: Updates to Terraform modules + - name: NuGet + color: "#07497f" + description: Updates to NuGet packages From e0c432596248785fab0c1b768d64c2b806ff6c30 Mon Sep 17 00:00:00 2001 From: RJ Hollberg Date: Fri, 25 Jul 2025 09:30:42 -0600 Subject: [PATCH 7/9] chore: add dummy VS solution --- Common.props | 123 ++++++++++++++++++++++++++++++ Fake.sln | 101 ++++++++++++++++++++++++ src/Fake/Class1.cs | 22 ++++++ src/Fake/Fake.csproj | 29 +++++++ src/Fake/PublicAPI.Shipped.txt | 0 src/Fake/PublicAPI.Unshipped.txt | 0 src/Production.props | 73 ++++++++++++++++++ test/.editorconfig | 36 +++++++++ test/Fake.Tests/Class1Tests.cs | 56 ++++++++++++++ test/Fake.Tests/Fake.Tests.csproj | 39 ++++++++++ test/Test.props | 67 ++++++++++++++++ test/Test.runsettings | 25 ++++++ 12 files changed, 571 insertions(+) create mode 100644 Common.props create mode 100644 Fake.sln create mode 100644 src/Fake/Class1.cs create mode 100644 src/Fake/Fake.csproj create mode 100644 src/Fake/PublicAPI.Shipped.txt create mode 100644 src/Fake/PublicAPI.Unshipped.txt create mode 100644 src/Production.props create mode 100644 test/.editorconfig create mode 100644 test/Fake.Tests/Class1Tests.cs create mode 100644 test/Fake.Tests/Fake.Tests.csproj create mode 100644 test/Test.props create mode 100644 test/Test.runsettings diff --git a/Common.props b/Common.props new file mode 100644 index 0000000..e615950 --- /dev/null +++ b/Common.props @@ -0,0 +1,123 @@ + + + + + + enable + + + + latest-all + true + false + + + + + + 9.0 + + + + 9.0 + + + + 9.0 + + + + 9.0 + + + + 9.0 + + + + 9.0 + + + + 9.0 + + + + 9.0 + + + + 9.0 + + + + + + + $(DefineConstants);CSHARP10 + disable + + + + $(DefineConstants);CSHARP10;CSHARP11 + disable + + + + $(DefineConstants);CSHARP10;CSHARP11;CSHARP12 + disable + + + + $(DefineConstants);CSHARP10;CSHARP11;CSHARP12;CSHARP13 + disable + + + + + + + + + + + + + + + + + + + + + + + + + + + <_AllProps>$(MSBuildAllProjects) + + + + <_Props Include="@(Property)" /> + + + + + + + + diff --git a/Fake.sln b/Fake.sln new file mode 100644 index 0000000..4505e28 --- /dev/null +++ b/Fake.sln @@ -0,0 +1,101 @@ +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36221.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".config", ".config", "{8019375E-8EF8-4A58-9309-0A356DB0491D}" + ProjectSection(SolutionItems) = preProject + .config\dotnet-tools.json = .config\dotnet-tools.json + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".github", ".github", "{B50175D7-072F-45EB-8E70-8ACB81B55024}" + ProjectSection(SolutionItems) = preProject + .github\CODEOWNERS = .github\CODEOWNERS + .github\copilot-instructions.md = .github\copilot-instructions.md + .github\dependabot.yml = .github\dependabot.yml + .github\pull_request_template.md = .github\pull_request_template.md + .github\settings.yml = .github\settings.yml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ISSUE_TEMPLATE", "ISSUE_TEMPLATE", "{261C00A6-E9BA-4EFC-9992-C75061255EED}" + ProjectSection(SolutionItems) = preProject + .github\ISSUE_TEMPLATE\01_bug_report.yml = .github\ISSUE_TEMPLATE\01_bug_report.yml + .github\ISSUE_TEMPLATE\02_performance_issue.yml = .github\ISSUE_TEMPLATE\02_performance_issue.yml + .github\ISSUE_TEMPLATE\03_feature_request.yml = .github\ISSUE_TEMPLATE\03_feature_request.yml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflows", "workflows", "{C7A64F19-DF59-4B16-A9C9-5D317FCF26CD}" + ProjectSection(SolutionItems) = preProject + .github\workflows\code-coverage.yml = .github\workflows\code-coverage.yml + .github\workflows\codecov.yml = .github\workflows\codecov.yml + .github\workflows\dotnet.yml = .github\workflows\dotnet.yml + .github\workflows\template-sync.yml = .github\workflows\template-sync.yml + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{8EC462FD-D22E-90A8-E5CE-7E832BA40C5D}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + .gitattributes = .gitattributes + .gitignore = .gitignore + .gitmessage = .gitmessage + .vsconfig = .vsconfig + Build.ps1 = Build.ps1 + build.sh = build.sh + Common.props = Common.props + CONTRIBUTING.md = CONTRIBUTING.md + GitReleaseManager.yml = GitReleaseManager.yml + GitVersion.yml = GitVersion.yml + global.json = global.json + LICENSE = LICENSE + nuget.config = nuget.config + README.md = README.md + SECURITY.md = SECURITY.md + StyleCop.json = StyleCop.json + SUPPORT.md = SUPPORT.md + Test.ps1 = Test.ps1 + test.sh = test.sh + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}" + ProjectSection(SolutionItems) = preProject + src\Production.props = src\Production.props + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fake", "src\Fake\Fake.csproj", "{480242FD-3FE7-4E71-9A1F-0FC446F1D20B}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{E5056391-64A9-4E23-B6F7-9596973E2D46}" + ProjectSection(SolutionItems) = preProject + test\.editorconfig = test\.editorconfig + test\Test.props = test\Test.props + test\Test.runsettings = test\Test.runsettings + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Fake.Tests", "test\Fake.Tests\Fake.Tests.csproj", "{0AEDD51E-D879-4F43-80F4-A3F6E9DF2B06}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {480242FD-3FE7-4E71-9A1F-0FC446F1D20B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {480242FD-3FE7-4E71-9A1F-0FC446F1D20B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {480242FD-3FE7-4E71-9A1F-0FC446F1D20B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {480242FD-3FE7-4E71-9A1F-0FC446F1D20B}.Release|Any CPU.Build.0 = Release|Any CPU + {0AEDD51E-D879-4F43-80F4-A3F6E9DF2B06}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0AEDD51E-D879-4F43-80F4-A3F6E9DF2B06}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0AEDD51E-D879-4F43-80F4-A3F6E9DF2B06}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0AEDD51E-D879-4F43-80F4-A3F6E9DF2B06}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {261C00A6-E9BA-4EFC-9992-C75061255EED} = {B50175D7-072F-45EB-8E70-8ACB81B55024} + {C7A64F19-DF59-4B16-A9C9-5D317FCF26CD} = {B50175D7-072F-45EB-8E70-8ACB81B55024} + {480242FD-3FE7-4E71-9A1F-0FC446F1D20B} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8} + {0AEDD51E-D879-4F43-80F4-A3F6E9DF2B06} = {E5056391-64A9-4E23-B6F7-9596973E2D46} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {59A0E416-6964-4EC2-93F4-8B2EA777E49D} + EndGlobalSection +EndGlobal diff --git a/src/Fake/Class1.cs b/src/Fake/Class1.cs new file mode 100644 index 0000000..19c80f6 --- /dev/null +++ b/src/Fake/Class1.cs @@ -0,0 +1,22 @@ +namespace Fake +{ + /// + /// Represents a class with no specific functionality. + /// + public static class Class1 + { + /// + /// Performs a calculation on the provided value. + /// + /// The input value. + /// The calculated result. + public static int Calculate(int value) + { +#if NETSTANDARD2_0 + return value * 2; +#elif NET9_0 + return value * 3; +#endif + } + } +} diff --git a/src/Fake/Fake.csproj b/src/Fake/Fake.csproj new file mode 100644 index 0000000..dda7a56 --- /dev/null +++ b/src/Fake/Fake.csproj @@ -0,0 +1,29 @@ + + + + + + netstandard2.0;net9.0 + + + + + + + + + + + + + + diff --git a/src/Fake/PublicAPI.Shipped.txt b/src/Fake/PublicAPI.Shipped.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Fake/PublicAPI.Unshipped.txt b/src/Fake/PublicAPI.Unshipped.txt new file mode 100644 index 0000000..e69de29 diff --git a/src/Production.props b/src/Production.props new file mode 100644 index 0000000..d369728 --- /dev/null +++ b/src/Production.props @@ -0,0 +1,73 @@ + + + + + + true + true + + + + RJ Hollberg + Copyright © $([System.DateTime]::Now.Year) RJ Hollberg. All rights reserved. + + true + Icon.png + LICENSE + README.md + $(PackageTags) + false + false + + + + true + git + + + + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + true + portable + true + true + snupkg + + + + true + true + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/.editorconfig b/test/.editorconfig new file mode 100644 index 0000000..bd95fde --- /dev/null +++ b/test/.editorconfig @@ -0,0 +1,36 @@ +#─────────────────────────────────────────────────────────────────────────────── +# These rules are unnecessary for test code: +#─────────────────────────────────────────────────────────────────────────────── + +[*.cs] + +# CodeAnalysis rules +# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ +dotnet_diagnostic.CA1054.severity = none # URI-like parameters should not be strings +dotnet_diagnostic.CA1063.severity = none # Implement IDisposable Correctly +dotnet_diagnostic.CA1303.severity = none # Do not pass literals as localized parameters +dotnet_diagnostic.CA1304.severity = none # Specify CultureInfo +dotnet_diagnostic.CA1305.severity = none # Specify IFormatProvider +dotnet_diagnostic.CA1307.severity = none # Specify StringComparison for clarity +dotnet_diagnostic.CA1308.severity = none # Normalize strings to uppercase +dotnet_diagnostic.CA1707.severity = none # Identifiers should not contain underscores +dotnet_diagnostic.CA1816.severity = none # Dispose methods should call SuppressFinalize +dotnet_diagnostic.CA1822.severity = none # Mark members as static +dotnet_diagnostic.CA2263.severity = none # Prefer generic overload when type is known +dotnet_diagnostic.CA5394.severity = none # Do not use insecure randomness + +# Compiler warnings +# https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/compiler-messages/ +dotnet_diagnostic.CS1591.severity = none # Missing XML comment for publicly visible type or member +dotnet_diagnostic.CS8002.severity = none # Referenced assembly does not have a strong name + +# StyleCop rules +# https://github.com/DotNetAnalyzers/StyleCopAnalyzers/tree/master/documentation +dotnet_diagnostic.SA0001.severity = none # XML comment analysis disabled +dotnet_diagnostic.SA1124.severity = none # Do not use regions +dotnet_diagnostic.SA1600.severity = none # Elements should be documented +dotnet_diagnostic.SA1601.severity = none # Partial elements should be documented +dotnet_diagnostic.SA1604.severity = none # Element documentation should have summary +dotnet_diagnostic.SA1605.severity = none # Partial element documentation should have summary +dotnet_diagnostic.SA1611.severity = none # Element parameters should be documented +dotnet_diagnostic.SA1619.severity = none # Generic type parameters should be documented partial class diff --git a/test/Fake.Tests/Class1Tests.cs b/test/Fake.Tests/Class1Tests.cs new file mode 100644 index 0000000..e52f12c --- /dev/null +++ b/test/Fake.Tests/Class1Tests.cs @@ -0,0 +1,56 @@ +using Xunit; + +namespace Fake +{ + public class Class1Tests + { + [Theory] +#if NET9_0 + [InlineData(1, 3)] + [InlineData(2, 6)] + [InlineData(3, 9)] +#else + [InlineData(1, 2)] + [InlineData(2, 4)] + [InlineData(3, 6)] +#endif + public void TestCompilerSwitches_OnAttributes(int given, int expected) + { + // Act + var result = Class1.Calculate(given); + + // Assert + Assert.Equal(expected, result); + } + + [Fact] + public void TestCompilerSwitches_OnCode() + { +#if NET462 + Assert.Equal(2, Class1.Calculate(1)); +#elif NET47 + Assert.Equal(2, Class1.Calculate(1)); +#elif NET471 + Assert.Equal(2, Class1.Calculate(1)); +#elif NET472 + Assert.Equal(2, Class1.Calculate(1)); +#elif NET48 + Assert.Equal(2, Class1.Calculate(1)); +#elif NET481 + Assert.Equal(2, Class1.Calculate(1)); +#elif NETCOREAPP3_1 + Assert.Equal(2, Class1.Calculate(1)); +#elif NET5_0 + Assert.Equal(2, Class1.Calculate(1)); +#elif NET6_0 + Assert.Equal(2, Class1.Calculate(1)); +#elif NET7_0 + Assert.Equal(2, Class1.Calculate(1)); +#elif NET8_0 + Assert.Equal(2, Class1.Calculate(1)); +#elif NET9_0 + Assert.Equal(3, Class1.Calculate(1)); +#endif + } + } +} diff --git a/test/Fake.Tests/Fake.Tests.csproj b/test/Fake.Tests/Fake.Tests.csproj new file mode 100644 index 0000000..8eae12a --- /dev/null +++ b/test/Fake.Tests/Fake.Tests.csproj @@ -0,0 +1,39 @@ + + + + + + net462;net47;net471;net472;net48;net481;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0;net9.0 + Fake + + + + + + + + + + + + + + + + + + + + + diff --git a/test/Test.props b/test/Test.props new file mode 100644 index 0000000..1676153 --- /dev/null +++ b/test/Test.props @@ -0,0 +1,67 @@ + + + + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/Test.runsettings b/test/Test.runsettings new file mode 100644 index 0000000..b74fdcf --- /dev/null +++ b/test/Test.runsettings @@ -0,0 +1,25 @@ + + + + + + + + cobertura + + Obsolete,GeneratedCode,CompilerGenerated + + + + false + false + false + true + + true + MissingAll + + + + + From ed12a15030efed914596c53f86fcef41905579e3 Mon Sep 17 00:00:00 2001 From: RJ Hollberg Date: Fri, 25 Jul 2025 12:00:41 -0600 Subject: [PATCH 8/9] chore: add build scripts --- Build.ps1 | 66 +++++++++++++++++++++++++++++++++++++++++ Test.ps1 | 71 ++++++++++++++++++++++++++++++++++++++++++++ build.sh | 63 +++++++++++++++++++++++++++++++++++++++ test.sh | 88 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 288 insertions(+) create mode 100644 Build.ps1 create mode 100644 Test.ps1 create mode 100644 build.sh create mode 100644 test.sh diff --git a/Build.ps1 b/Build.ps1 new file mode 100644 index 0000000..086dd83 --- /dev/null +++ b/Build.ps1 @@ -0,0 +1,66 @@ +<# +.SYNOPSIS +Build script for the NuGet package template. + +.DESCRIPTION +This script handles various setup and build tasks for the NuGet package template. +#> + +#─────────────────────────────────────────────────────────────────────────────── +# Function Definitions +#─────────────────────────────────────────────────────────────────────────────── + +# Writes informational messages +function Write-HostInfo($message) { + Write-Host $message -ForegroundColor Blue +} + +# Writes success messages +function Write-HostSuccess($message) { + Write-Host $message -ForegroundColor Green +} + +# Checks exit code and exits on failure +function Assert-ExitCode($command) { + if ($LASTEXITCODE -ne 0) { + Write-Host "$command failed with exit code $LASTEXITCODE" -ForegroundColor Red + exit $LASTEXITCODE + } +} + +#─────────────────────────────────────────────────────────────────────────────── +# Script Execution +#─────────────────────────────────────────────────────────────────────────────── + +# Configure git to use the existing .gitmessage template for this repo +git config --local commit.template .gitmessage +Write-HostSuccess 'Git commit message template configured' + +# Clean previous build artifacts +Write-Host +Write-HostInfo 'Cleaning previous build artifacts...' +dotnet clean --nologo +Get-ChildItem -Path $PSScriptRoot -Include 'TestResults' -Directory -Recurse ` +| ForEach-Object { Remove-Item -Path $_.FullName -Recurse -Force } +Assert-ExitCode 'Clean' + +# Restore .NET tools +Write-Host +Write-HostInfo 'Restoring .NET tools...' +dotnet tool restore +Assert-ExitCode 'Tool Restore' + +# Restore NuGet packages +Write-Host +Write-HostInfo 'Restoring NuGet packages...' +dotnet restore --nologo +Assert-ExitCode 'Package Restore' + +# Build the solution +Write-Host +Write-HostInfo 'Building solution...' +dotnet build --nologo --no-restore +Assert-ExitCode 'Build' + +Write-Host +Write-HostSuccess 'Build completed successfully.' diff --git a/Test.ps1 b/Test.ps1 new file mode 100644 index 0000000..55eadd8 --- /dev/null +++ b/Test.ps1 @@ -0,0 +1,71 @@ +<# +.SYNOPSIS +Test script for the NuGet package template. + +.DESCRIPTION +This script runs tests with code coverage and generates a report. +It calls the build script first to ensure everything is built correctly. +#> + +#─────────────────────────────────────────────────────────────────────────────── +# Variable Definitions +#─────────────────────────────────────────────────────────────────────────────── + +$TestDir = Join-Path $PSScriptRoot 'test' +$ResultsDir = Join-Path $TestDir 'TestResults' + +#─────────────────────────────────────────────────────────────────────────────── +# Prerequisites +#─────────────────────────────────────────────────────────────────────────────── + +# Import the build script and execute it +. (Join-Path $PSScriptRoot 'build.ps1') + +#─────────────────────────────────────────────────────────────────────────────── +# Function Definitions +#─────────────────────────────────────────────────────────────────────────────── + +# Function to display the coverage summary +function Show-CoverageSummary($file) { + Get-Content $file | ForEach-Object { + if ($_ -Match "Line coverage:|Branch coverage:|Method coverage:") { + Write-HostSuccess $_ + } + else { + Write-Host $_ + } + } +} + +#─────────────────────────────────────────────────────────────────────────────── +# Script Execution +#─────────────────────────────────────────────────────────────────────────────── + +# Run the tests with code coverage +Write-Host +Write-HostInfo 'Running tests with code coverage...' +dotnet test ` + --nologo ` + --no-restore ` + --no-build ` + --collect:'XPlat Code Coverage' ` + --settings:"$(Join-Path $TestDir 'Test.runsettings')" +Assert-ExitCode 'Tests' + +# Generate reports from the coverage results +Write-Host +Write-HostInfo 'Generating coverage report...' +reportgenerator ` + -reports:"$(Join-Path '**' 'coverage.cobertura.xml')" ` + -reporttypes:'HtmlInline;TextSummary' ` + -targetdir:"$ResultsDir" +Assert-ExitCode 'Report Generation' + +# Display coverage results in the console +Write-Host +Show-CoverageSummary (Join-Path $ResultsDir 'Summary.txt') +Write-Host +Write-HostSuccess "Tests complete. Report generated in: $ResultsDir" + +# Open the HTML report +Start-Process (Join-Path $ResultsDir 'index.html') diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..2410d79 --- /dev/null +++ b/build.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# +# Build script for the NuGet package template. +# +# This script handles various setup and build tasks for the NuGet package template. + +#─────────────────────────────────────────────────────────────────────────────── +# Function Definitions +#─────────────────────────────────────────────────────────────────────────────── + +# Writes informational messages +echo_info() { + echo -e "\e[34m$1\e[0m" +} + +# Writes success messages +echo_success() { + echo -e "\e[32m$1\e[0m" +} + +# Checks exit code and exits on failure +assert_exit_code() { + if [ $? -ne 0 ]; then + echo -e "\e[31m$1 failed with exit code $?\e[0m" + exit $? + fi +} + +#─────────────────────────────────────────────────────────────────────────────── +# Script Execution +#─────────────────────────────────────────────────────────────────────────────── + +# Configure git to use the existing .gitmessage template for this repo +git config --local commit.template .gitmessage +echo_success 'Git commit message template configured' + +# Clean previous build artifacts +echo +echo_info 'Cleaning previous build artifacts...' +dotnet clean --nologo +find "$(dirname "$0")" -name 'TestResults' -type d -exec rm -rf {} + +assert_exit_code 'Clean' + +# Restore .NET tools +echo +echo_info 'Restoring .NET tools...' +dotnet tool restore +assert_exit_code 'Tool Restore' + +# Restore NuGet packages +echo +echo_info 'Restoring NuGet packages...' +dotnet restore --nologo +assert_exit_code 'Package Restore' + +# Build the solution +echo +echo_info 'Building solution...' +dotnet build --nologo --no-restore +assert_exit_code 'Build' + +echo +echo_success 'Build completed successfully.' diff --git a/test.sh b/test.sh new file mode 100644 index 0000000..a5ee49b --- /dev/null +++ b/test.sh @@ -0,0 +1,88 @@ +#!/usr/bin/env bash +# +# Test script for the NuGet package template. +# +# This script runs tests with code coverage and generates a report. +# It calls the build script first to ensure everything is built correctly. + +#─────────────────────────────────────────────────────────────────────────────── +# Variable Definitions +#─────────────────────────────────────────────────────────────────────────────── + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +TEST_DIR="$SCRIPT_DIR/test" +RESULTS_DIR="$TEST_DIR/TestResults" +HTML_FILE="$RESULTS_DIR/index.html" + +#─────────────────────────────────────────────────────────────────────────────── +# Prerequisites +#─────────────────────────────────────────────────────────────────────────────── + +# Import the build script and execute it +. "$SCRIPT_DIR/build.sh" + +#─────────────────────────────────────────────────────────────────────────────── +# Function Definitions +#─────────────────────────────────────────────────────────────────────────────── + +# Function to display the coverage summary +show_coverage_summary() { + while IFS= read -r line; do + if [[ $line =~ (Line coverage:|Branch coverage:|Method coverage:) ]]; then + echo_success "$line" + else + echo "$line" + fi + done < "$1" +} + +#─────────────────────────────────────────────────────────────────────────────── +# Script Execution +#─────────────────────────────────────────────────────────────────────────────── + +# Run the tests with code coverage +echo +echo_info 'Running tests with code coverage...' +dotnet test \ + --nologo \ + --no-restore \ + --no-build \ + --collect:'XPlat Code Coverage' \ + --settings:"$TEST_DIR/Test.runsettings" +assert_exit_code 'Tests' + +# Generate reports from the coverage results +echo +echo_info 'Generating coverage report...' +reportgenerator \ + -reports:'**/coverage.cobertura.xml' \ + -reporttypes:'HtmlInline;TextSummary' \ + -targetdir:"$RESULTS_DIR" +assert_exit_code 'Report Generation' + +# Display coverage results in the console +echo +show_coverage_summary "$RESULTS_DIR/Summary.txt" +echo +echo_success "Tests complete. Report generated in: $RESULTS_DIR" + +# Open the HTML report +if [[ "$OSTYPE" == "darwin"* ]]; then # macOS + open "$HTML_FILE" +elif [[ "$OSTYPE" == "linux-gnu"* ]]; then # Linux + if command -v xdg-open > /dev/null; then + xdg-open "$HTML_FILE" + elif command -v gnome-open > /dev/null; then + gnome-open "$HTML_FILE" + fi +elif [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "cygwin" ]] || [[ "$OSTYPE" == "win32" ]]; then # Windows + start "$HTML_FILE" +elif [[ -n "$(uname -r | grep -i microsoft)" ]]; then # Windows Subsystem for Linux (WSL) + if command -v wslview > /dev/null; then + wslview "$HTML_FILE" + elif command -v powershell.exe > /dev/null; then + powershell.exe -Command "Start-Process '$(wslpath -w "$HTML_FILE")'" + elif command -v cmd.exe > /dev/null; then + cmd.exe /c start "$(wslpath -w "$HTML_FILE")" + fi +fi From 307c4cf032d72816d6b6cdab5df96ef0e43d7df6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 7 Sep 2025 00:15:26 +0000 Subject: [PATCH 9/9] chore: Bump gitversion.tool from 6.3.0 to 6.4.0 --- updated-dependencies: - dependency-name: gitversion.tool dependency-version: 6.4.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .config/dotnet-tools.json | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index a56873e..f844c72 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -4,18 +4,24 @@ "tools": { "dotnet-reportgenerator-globaltool": { "version": "5.4.8", - "commands": ["reportgenerator"], + "commands": [ + "reportgenerator" + ], "rollForward": false }, "gitreleasemanager.tool": { "version": "0.20.0", - "commands": ["dotnet-gitreleasemanager"], + "commands": [ + "dotnet-gitreleasemanager" + ], "rollForward": false }, "gitversion.tool": { - "version": "6.3.0", - "commands": ["dotnet-gitversion"], + "version": "6.4.0", + "commands": [ + "dotnet-gitversion" + ], "rollForward": false } } -} +} \ No newline at end of file