Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"hooks": [
{
"type": "command",
"command": "f=$(jq -r '.tool_input.file_path // .tool_input.notebook_path // empty'); case \"$f\" in \"\"|*/bin/*|*/obj/*) exit 0;; esac; case \"$f\" in *.md|*.json|*.jsonc|*.yml|*.yaml|*.toml|*.xml|*.csproj|*.slnx) ;; *) exit 0;; esac; command -v dprint >/dev/null 2>&1 && [ -f \"$f\" ] && dprint fmt \"$f\" 2>&1; true",
"command": "f=$(jq -r '.tool_input.file_path // .tool_input.notebook_path // empty'); case \"$f\" in \"\"|*/build/*) exit 0;; esac; case \"$f\" in *.md|*.json|*.jsonc|*.yml|*.yaml|*.toml|*.xml|*.csproj|*.slnx) ;; *) exit 0;; esac; command -v dprint >/dev/null 2>&1 && [ -f \"$f\" ] && dprint fmt \"$f\" 2>&1; true",
"statusMessage": "Formatting (dprint)..."
},
{
Expand All @@ -19,7 +19,7 @@
},
{
"type": "command",
"command": "f=$(jq -r '.tool_input.file_path // .tool_input.notebook_path // empty'); case \"$f\" in \"\"|*/bin/*|*/obj/*|*.svg) exit 0;; esac; command -v npx >/dev/null 2>&1 || exit 0; if [ -f \"$f\" ]; then out=$(npx --yes cspell@10.0.1 lint --config tests/linters/.cspell.json --no-progress \"$f\" 2>&1); [ $? -ne 0 ] && { echo \"$out\" >&2; exit 2; }; fi; true",
"command": "f=$(jq -r '.tool_input.file_path // .tool_input.notebook_path // empty'); case \"$f\" in \"\"|*/build/*|*.svg) exit 0;; esac; command -v npx >/dev/null 2>&1 || exit 0; if [ -f \"$f\" ]; then out=$(npx --yes cspell@10.0.1 lint --config tests/linters/.cspell.json --no-progress \"$f\" 2>&1); [ $? -ne 0 ] && { echo \"$out\" >&2; exit 2; }; fi; true",
"statusMessage": "Spell checking (CSpell)..."
}
]
Expand Down
7 changes: 7 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
"reportgenerator"
],
"rollForward": false
},
"xmldoc2markdown": {
"version": "6.0.0",
"commands": [
"xmldoc2md"
],
"rollForward": false
}
}
}
97 changes: 97 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# The display name of the workflow, shown in the "Actions" tab of the GitHub repository and in the checks of a commit or pull request
name: Docs

# Defines the events that trigger this workflow; unlike "Linters" and "Tests", which run on every push to any branch, this workflow only runs on
# pushes to "main" - it deploys the documentation website to GitHub Pages, so it only ever needs to run against what is actually published
on:
push:
branches:
- main

# Grants the workflow only the permissions the GitHub Pages deployment needs: reading the repository contents, writing to the Pages deployment,
# and requesting the OpenID Connect token GitHub Pages uses to verify the deployment came from this workflow
permissions:
contents: read
pages: write
id-token: write

# Ensures that at most one deployment runs at a time and that a newer push is never overtaken by an older one still in flight; unlike most
# concurrency groups, an in-progress Pages deployment is allowed to finish rather than being cancelled, since a cancelled deployment can leave the
# site in a partially updated state
concurrency:
group: pages
cancel-in-progress: false

# Defines the jobs that make up the workflow; building the site and deploying it are two separate jobs so that the deployment step only runs
# through the dedicated "github-pages" environment, which is what makes the deployment show up in the repository's "Environments" and gives it
# its own audit trail, separate from the build
jobs:
# Builds the ProperDocs site, including the generated "api" section (see docs/developer-manual/tooling/documentation-website.md), and uploads it as
# a Pages artifact; runs on the latest Ubuntu image, which is the fastest and cheapest of the available runners
build:
name: Build Site
runs-on: ubuntu-latest

steps:
# Checks out the repository into the runner's working directory; the "actions/checkout" action is pinned to a major version to receive
# non-breaking updates automatically
- name: Checkout Repository
uses: actions/checkout@v7

# Installs the .NET SDK; the version is read from "global.json" in the repository root, so this workflow can never drift from the exact
# version pinned there (see Dependency Management); the generator script (below) shells out to "dotnet" to build the framework and to run
# the pinned xmldoc2md local tool
- name: Set Up .NET
uses: actions/setup-dotnet@v6
with:
global-json-file: global.json

# Restores the local .NET tools declared in ".config/dotnet-tools.json", which is where xmldoc2md, the C# XML documentation to Markdown
# generator the "api" section uses, is pinned (see Documentation Website and Dependency Management)
- name: Restore .NET Tools
run: dotnet tool restore

# Installs Python, pinned to an exact patch version, so that ProperDocs and its plugins run in a stable and reproducible environment; the
# "actions/setup-python" action is pinned to a major version to receive non-breaking updates automatically
- name: Set Up Python
uses: actions/setup-python@v7
with:
python-version: "3.13.14"

# Installs ProperDocs, the Material theme, and the plugins that generate the site's navigation and its "api" section, all pinned to exact
# versions in "requirements.txt" (see Dependency Management)
- name: Install Documentation Dependencies
run: python -m pip install --requirement requirements.txt

# Builds the static site into "build/documentation-website/" (see "site_dir" in "properdocs.yml"); this regenerates the "docs/api" section
# from the framework's current XML documentation comments as part of the build (see Documentation Website) - nothing under "docs/api" is
# ever committed, so this step is what produces it, every time
- name: Build Documentation Website
run: properdocs build

# Configures GitHub Pages for the repository, so the following upload step knows where to send the built site
- name: Configure Pages
uses: actions/configure-pages@v6

# Uploads the built site as the artifact that the "deploy" job below publishes to GitHub Pages
- name: Upload Pages Artifact
uses: actions/upload-pages-artifact@v5
with:
path: build/documentation-website

# Publishes the artifact the "build" job uploaded to GitHub Pages, through the "github-pages" deployment environment
deploy:
name: Deploy to GitHub Pages
needs: build
runs-on: ubuntu-latest

environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

steps:
# Publishes the previously uploaded artifact to GitHub Pages; "id: deployment" lets the "environment.url" above surface the live URL on
# the workflow run and in the repository's "Environments" tab
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v5
28 changes: 15 additions & 13 deletions .github/workflows/linters.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,30 +29,32 @@ jobs:
with:
node-version: 24

# Installs the linters and the code formatter globally, so that they are available as commands in the subsequent steps; installing them in a
# dedicated step keeps the linter steps below focused on just running the tools
# Installs the exact versions of the linters and the code formatter declared in "package.json" and locked in "package-lock.json" (see
# Dependency Management); "ci" (rather than "install") fails instead of silently updating the lock file if it would no longer match
# "package.json", the same guarantee "--locked-mode" gives the NuGet restore in the Tests workflow
- name: Install Linters
run: npm install --global dprint@0.55.1 cspell@10.0.1 markdownlint-cli2@0.23.0
run: npm ci

# Runs the dprint code formatter in check mode; "check" only verifies that all files are already formatted and exits with a non-zero status code
# if any file is not, but unlike "dprint fmt" it never modifies any file; dprint automatically discovers the "dprint.json" stub in the
# repository root, which extends the real configuration in "tests/linters", so no configuration path has to be passed explicitly, and the
# "**/*" glob makes dprint check the whole repository (relative to the working directory)
# if any file is not, but unlike "dprint fmt" it never modifies any file; dprint automatically discovers "dprint.json" in the repository root,
# so no configuration path has to be passed explicitly, and the "**/*" glob makes dprint check the whole repository (relative to the working
# directory); "npx" resolves the version "npm ci" just installed into "node_modules/.bin" rather than downloading one
- name: Check Formatting (dprint)
run: dprint check "**/*"
run: npx dprint check "**/*"

# Runs the CSpell spell checker over every file in the repository; the "lint" command reports spelling mistakes and exits with a non-zero status
# code if any are found, the configuration path is passed explicitly, and "--no-progress" suppresses the per-file progress output to keep the
# log readable; the "if" ensures that the step runs (unless the workflow was cancelled), even if the previous linter reported an error and
# exited with a non-zero exit code, so that the job runs all linters instead of stopping at the first failure
- name: Spell Check (CSpell)
if: ${{ !cancelled() }}
run: cspell lint --config tests/linters/.cspell.json --no-progress "**/*"
run: npx cspell lint --config tests/linters/.cspell.json --no-progress "**/*"

# Runs the MarkdownLint linter over all Markdown files in the repository; the configuration path is passed explicitly via "--config", and the
# build output directories are excluded using markdownlint-cli2's "#"-prefixed negated globs (markdownlint-cli2 has no "--ignore" flag), so that
# only the project's own documentation is linted; the "if" ensures that the step runs (unless the workflow was cancelled), even if the previous
# linter reported an error and exited with a non-zero exit code, so that the job runs all linters instead of stopping at the first failure
# Runs the MarkdownLint linter over all Markdown files in the repository; the configuration path is passed explicitly via "--config", and build
# output and "node_modules" (unlike dprint and CSpell, markdownlint-cli2 does not ignore it by default) are excluded using markdownlint-cli2's
# "#"-prefixed negated globs (it has no "--ignore" flag), so that only the project's own documentation is linted; the "if" ensures that the
# step runs (unless the workflow was cancelled), even if the previous linter reported an error and exited with a non-zero exit code, so that
# the job runs all linters instead of stopping at the first failure
- name: Lint Markdown (MarkdownLint)
if: ${{ !cancelled() }}
run: markdownlint-cli2 --config tests/linters/.markdownlint.yml "**/*.md" "#**/bin/**" "#**/obj/**"
run: npx markdownlint-cli2 --config tests/linters/.markdownlint.yml "**/*.md" "#**/build/**" "#**/node_modules/**" "#**/.venv/**"
15 changes: 11 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,18 @@ Thumbs.db
!.vscode/tasks.shared.json
*.launch
*.sublime-workspace
/.idea
.idea

# Build output
bin/
obj/
# Installed packages
node_modules/
.venv/

# Build output (redirected here from every project's own folder, and from the documentation website, see Architecture and Documentation Website)
/build/
__pycache__/

# Personal, unreviewed NPM install-script policy (see docs/developer-manual/tooling/developer-setup.md)
/.npmrc

# Test results and code coverage reports
TestResults/
Expand Down
18 changes: 18 additions & 0 deletions .vscode/launch.shared.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"version": "0.2.0",
"configurations": [
// Debugs the sample app, this builds the project via the "Build Sample App" task (see "tasks.shared.json") before attaching the debugger to
// the resulting executable
{
"name": "Debug Sample App",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "Build Sample App",
"program": "${workspaceFolder}/build/sample-app/bin/Debug/net10.0/CLI.NET Core Sample App.dll",
"args": [],
"cwd": "${workspaceFolder}/source/sample-app",
"console": "integratedTerminal",
"stopAtEntry": false,
},
],
}
13 changes: 7 additions & 6 deletions .vscode/settings.shared.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,23 @@
// Excludes certain files from being displayed in the file explorer
"files.exclude": {
".VSCodeCounter": true,
"**/__pycache__": true,
"**/.DS_Store": true,
"**/.git": true,
"**/bin": true,
"**/obj": true,
"**/.venv": true,
"**/node_modules": true,
"**/Thumbs.db": true,
},

// Excludes certain files from being watched by the file watcher, this is required, because if the data directory is inside of the workspace, then
// Visual Studio Code will watch the entire directory, which can not only cause performance issues, but will also cause the file watcher to run
// out of file handles, which are limited by the operating system, that are necessary to watch the files
// out of file handles, which are limited by the operating system, that are necessary to watch the files; "/build" is anchored to the workspace
// root, the same as in "files.exclude" above, so "docs/build/" is still watched
"files.watcherExclude": {
".VSCodeCounter": true,
"**/.git/objects/**": true,
"**/.git/subtree-cache/**": true,
"**/bin": true,
"**/obj": true,
"/build": true,
},

// Specifies which Git branches are protected in this repository, Visual Studio will prevent users from committing to these branches (this only
Expand Down Expand Up @@ -69,7 +70,7 @@
"cSpell.import": ["${workspaceFolder}/tests/linters/.cspell.json"],

// Configures the Markdown linter MarkdownLint to use our custom configuration
"markdownlint.config": { "extends": "${workspaceFolder}/tests/linters/.markdownlint.yml" },
"markdownlint.configFile": "${workspaceFolder}/tests/linters/.markdownlint.yml",

// Configures the code formatter dprint
"dprint.verbose": true,
Expand Down
Loading