Template
Compare commits
15
Commits
fd614be89c
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
388c036ce6
|
||
|
|
3546994587
|
||
|
|
2f1e580e49
|
||
|
|
ad4aa99cfa
|
||
|
|
3074c580dc
|
||
|
|
8e3b5ebdfc
|
||
|
|
ec165d1425
|
||
|
|
4913ab7ecf
|
||
|
|
c5a4ba6103
|
||
|
|
4d25634091
|
||
|
|
9193f0b412
|
||
|
|
db57eed6c0
|
||
|
|
2be87a7da6
|
||
|
|
7d2ee5809b
|
||
|
|
7af0ee5bd6
|
@@ -0,0 +1,19 @@
|
|||||||
|
Follow [gitmoji](https://gitmoji.dev) conventions. Use the **emoji character** (not the `:shortcode:`).
|
||||||
|
|
||||||
|
## Format
|
||||||
|
|
||||||
|
```
|
||||||
|
<emoji> <imperative summary, third person>
|
||||||
|
|
||||||
|
<longer explanation of what and why, wrap at 72 chars>
|
||||||
|
|
||||||
|
<issue references, e.g. Closes #123, Fixes PROJ-456>
|
||||||
|
```
|
||||||
|
|
||||||
|
- Subject line under 72 characters.
|
||||||
|
- Third-person imperative mood ("Adds feature", not "Add feature" or "Added feature").
|
||||||
|
- Do not end the subject with a period.
|
||||||
|
- Separate subject, body, and footer with blank lines.
|
||||||
|
- Body and footer are **optional** — only include when the subject alone isn't self-explanatory or when issues need linking.
|
||||||
|
- Body explains **what** changed and **why**.
|
||||||
|
- Footer links related issues (GitHub `Closes #N` / Jira `PROJ-N`).
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# Project Guidelines
|
||||||
|
|
||||||
|
You are a senior software engineer and solution architect. Prioritize correctness, maintainability, and simplicity. Evaluate trade-offs before proposing solutions; prefer the least complex approach that meets requirements.
|
||||||
|
|
||||||
|
## Behaviour
|
||||||
|
|
||||||
|
- **Tone**: direct and concise — minimise prose, maximise actionable output.
|
||||||
|
- **Research first, act second** — always consult official documentation, codebase context, and project conventions **before** proposing or implementing changes. Never guess, assume API shapes, or rely on trial-and-error. If documentation is unclear or unavailable, say so and ask for guidance.
|
||||||
|
- When ambiguous or multiple approaches exist, **ask clarifying questions with 2–4 predefined options** (include trade-offs). Only proceed silently when intent is obvious.
|
||||||
|
- Briefly explain every suggestion: what it does, why, and how it fits the architecture.
|
||||||
|
- When goals conflict (e.g., performance vs readability), **favour performance** unless readability is significantly harmed.
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- When a project has a `README.md`, treat it as part of the implementation: any rename or restructure that touches type names, configuration sections, or project references must update the affected `README.md` **in the same commit**.
|
||||||
|
- Before opening a PR, scan each touched project's existing `README.md` (if any) for stale references.
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
---
|
||||||
|
description: "Use when editing files under docs/adr/. Enforces ADR immutability and supersession rules."
|
||||||
|
applyTo: "docs/adr/**"
|
||||||
|
---
|
||||||
|
# ADR Editing Rules
|
||||||
|
|
||||||
|
ADRs are append-only history. To create a new ADR, use the `new-adr` skill.
|
||||||
|
|
||||||
|
- **Accepted ADRs are immutable.** Do not change `Context`, `Decision Drivers`, `Considered Options`, or `Decision Outcome` after acceptance — write a new ADR that supersedes instead.
|
||||||
|
- **Permitted edits to accepted ADRs**: typo/grammar fixes, adding links to related ADRs, and updating the `status` field as part of supersession or deprecation.
|
||||||
|
- **Superseding**: set the predecessor's frontmatter to `status: superseded by ADR-NNNN`, update its `date`, and add a back-link in its body. Never delete the predecessor.
|
||||||
|
- **Filenames are permanent.** Do not renumber or rename existing ADRs even if numbers have gaps.
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
description: "Use when editing analyzer or code-style configuration: .editorconfig, .globalconfig, stylecop.json, .DotSettings."
|
||||||
|
applyTo: ".editorconfig,.globalconfig,stylecop.json,*.DotSettings"
|
||||||
|
---
|
||||||
|
# Analyzer & Style Configuration
|
||||||
|
|
||||||
|
These files are the source of truth for code style and analyzer severity. Changes have wide blast radius.
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> **Ask for explicit permission before editing.** State the rule(s), the new severity, and the rationale; wait for approval. Do not touch these files as part of unrelated work. The stated rationale belongs in the PR description.
|
||||||
|
|
||||||
|
## Guardrails
|
||||||
|
|
||||||
|
- **Do not relax a rule to silence a single occurrence.** Fix the code, or suppress narrowly with a justification comment in the offending file.
|
||||||
|
- New rules start at the **strictest justifiable severity**; downgrade later only with evidence.
|
||||||
|
- Never disable an entire analyzer category.
|
||||||
|
|
||||||
|
## File Roles
|
||||||
|
|
||||||
|
| File | Purpose |
|
||||||
|
| --- | --- |
|
||||||
|
| `.editorconfig` | Per-language formatting, naming rules, and analyzer severities scoped by file glob. |
|
||||||
|
| `.globalconfig` | Repo-wide analyzer severities not needing file-pattern scoping. |
|
||||||
|
| `stylecop.json` | StyleCop-specific settings (file headers, ordering, documentation). |
|
||||||
|
| `Solution.sln.DotSettings` | ReSharper/Rider mirror — **derived**, follows the others; do not lead changes here. |
|
||||||
|
|
||||||
|
## Coordination
|
||||||
|
|
||||||
|
- **A rule has one source of truth** across `.editorconfig`, `.globalconfig`, and `stylecop.json` — never duplicate.
|
||||||
|
- When a rule must appear in multiple files for IDE parity (e.g., mirrored to `Solution.sln.DotSettings`), severities **must match exactly**. Drift is a bug.
|
||||||
|
- StyleCop rules: configuration in `stylecop.json`, severity in `.editorconfig`.
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
description: "Use when writing API endpoints, routing, middleware, request/response handling, OpenAPI configuration, or HTTP pipeline setup in ASP.NET. Covers Minimal API conventions, error handling, and endpoint organisation."
|
||||||
|
---
|
||||||
|
# ASP.NET API Conventions
|
||||||
|
|
||||||
|
## Routing
|
||||||
|
|
||||||
|
- All endpoints live under `/api/v{apiVersion}/{resource}`.
|
||||||
|
- Default to `/api/v1` for projects without explicit API versioning.
|
||||||
|
|
||||||
|
## Endpoints
|
||||||
|
|
||||||
|
- Prefer **Minimal APIs**; use Controllers only when the added structure is justified.
|
||||||
|
- Group related endpoints using `MapGroup()` with a shared prefix and tag.
|
||||||
|
- Use **typed results** (`TypedResults.Ok()`, `TypedResults.NotFound()`) over untyped `Results` for OpenAPI metadata inference.
|
||||||
|
- Return **`ProblemDetails`** (RFC 9457) for all error responses — configure via `AddProblemDetails()`.
|
||||||
|
|
||||||
|
## Request Handling
|
||||||
|
|
||||||
|
- Bind request data with **`[AsParameters]`** for complex parameter sets.
|
||||||
|
- Validate input at the endpoint boundary — use **filters** or **`IValidatableObject`** to fail fast.
|
||||||
|
- Use **`CancellationToken`** on all async endpoints.
|
||||||
|
|
||||||
|
## Endpoint Organisation
|
||||||
|
|
||||||
|
- One file per resource or feature area (e.g., `UserEndpoints.cs`, `OrderEndpoints.cs`).
|
||||||
|
- Register via extension methods on `IEndpointRouteBuilder`: `MapUserEndpoints()`.
|
||||||
|
- Keep endpoint lambdas thin — delegate business logic to injected services.
|
||||||
|
|
||||||
|
## OpenAPI
|
||||||
|
|
||||||
|
- Annotate endpoints with `.WithTags()` for grouping in the generated spec.
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
description: "Use when writing or modifying C# source code. Covers non-obvious defaults not caught by analyzers."
|
||||||
|
applyTo: "**/*.cs"
|
||||||
|
---
|
||||||
|
# C# Conventions
|
||||||
|
|
||||||
|
Code style is enforced by `.editorconfig`, `.globalconfig`, and StyleCop analyzers — do not restate their rules.
|
||||||
|
|
||||||
|
## Non-Obvious Defaults
|
||||||
|
|
||||||
|
- XML doc comments required on public API in `src/` (suppressed in `tests/` and `samples/`).
|
||||||
|
- Avoid `null!` (null-forgiving operator) — fix the nullability flow instead of suppressing the warning.
|
||||||
|
|
||||||
|
## Patterns
|
||||||
|
|
||||||
|
- Prefer **records** for DTOs, value objects, and other immutable data carriers.
|
||||||
|
- Use `LoggerMessage`-generated `partial` methods on a `partial class` — never log inline (e.g., `logger.LogInformation(…)`).
|
||||||
|
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
---
|
||||||
|
description: "Use when editing Dockerfile, compose files, or Docker-related configuration. Covers guardrails for the multi-stage build and runtime image selection."
|
||||||
|
applyTo: "docker/**,compose*.yaml"
|
||||||
|
---
|
||||||
|
# Docker Conventions
|
||||||
|
|
||||||
|
`docker/Dockerfile` is a multi-stage pipeline — stage names and purposes are visible in the file itself.
|
||||||
|
|
||||||
|
## Guardrails
|
||||||
|
|
||||||
|
- **Build context** is always the repo root, not `docker/`.
|
||||||
|
- **`COPY --link`** is used intentionally for layer cache — do not replace with plain `COPY`.
|
||||||
|
- **Cache mounts** (`--mount=type=cache,target=/root/.nuget/packages`) must stay on restore, build, test, and publish steps.
|
||||||
|
- **Stage dependency chain** must be preserved (e.g., `build` → `restore`, `test` → `build`, `publish` → `test`).
|
||||||
|
- New stages should follow the existing pattern: `FROM <parent> AS <name>`.
|
||||||
|
|
||||||
|
## Build Args
|
||||||
|
|
||||||
|
- `RUNTIME_BASE`: `web` (ASP.NET), `app` (console), or `self-contained`
|
||||||
|
- `CONFIGURATION`: `Release` (default) or `Debug`
|
||||||
|
- `PUBLISHED_PROJECT`: Project name to publish (without path or extension)
|
||||||
|
- `DATABASE_PROJECT`: EF Core project for migration bundles
|
||||||
|
- `DBCONTEXT`: Optional DbContext name for migrations
|
||||||
|
|
||||||
|
## Image Selection
|
||||||
|
|
||||||
|
| Use Case | `RUNTIME_BASE` | Base Image |
|
||||||
|
|----------|----------------|------------|
|
||||||
|
| ASP.NET web apps | `web` | `aspnet:*-alpine-composite-extra` |
|
||||||
|
| Console / worker | `app` | `runtime:*-alpine-extra` |
|
||||||
|
| Self-contained | `self-contained` | `runtime-deps:*-alpine-extra` |
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
---
|
||||||
|
description: "README.md authoring: structure, callouts, diagrams, and assets."
|
||||||
|
applyTo: "**/README.md"
|
||||||
|
---
|
||||||
|
# README Style
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
Follow this ordering when sections apply; omit those that don't:
|
||||||
|
|
||||||
|
1. **Title** (`# <ProjectName>`) and one-sentence purpose.
|
||||||
|
1. **Getting Started** — minimal commands to consume or run the project.
|
||||||
|
1. **Features** / **Capabilities** — bulleted highlights.
|
||||||
|
1. **Configuration** — build args, environment variables, MSBuild properties.
|
||||||
|
1. **Usage Examples** — code or CLI snippets.
|
||||||
|
1. **Recommendations** / **Caveats** — known limitations, in callouts.
|
||||||
|
1. **Reference link definitions** at the bottom.
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
- Do not hard-wrap prose; one paragraph per line.
|
||||||
|
- Ordered lists: write every item as `1.` and let the renderer auto-number.
|
||||||
|
- Use reference-style links for external URLs in prose, with definitions at the bottom of the file. Inline links are fine in tables and for in-repo relative paths.
|
||||||
|
- Keep code examples minimal — strip boilerplate unless it is the point.
|
||||||
|
|
||||||
|
## Callouts
|
||||||
|
|
||||||
|
Use [GitHub-flavoured alerts](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax#alerts) for emphasis; reserve plain `>` blockquotes for quoted text.
|
||||||
|
|
||||||
|
| Alert | Use for |
|
||||||
|
| --- | --- |
|
||||||
|
| `> [!NOTE]` | Neutral context the reader should know |
|
||||||
|
| `> [!TIP]` | Optional best-practice |
|
||||||
|
| `> [!IMPORTANT]` | Required for correct usage |
|
||||||
|
| `> [!WARNING]` | Risk of breakage or data loss |
|
||||||
|
| `> [!CAUTION]` | Security or destructive-action risk |
|
||||||
|
|
||||||
|
## Mermaid Diagrams
|
||||||
|
|
||||||
|
- Match diagram type to intent: `flowchart` (processes), `sequenceDiagram` (interactions over time), `classDiagram` (type relationships), `erDiagram` (data models).
|
||||||
|
- Keep diagrams under ~15 nodes; split larger ones.
|
||||||
|
- No custom styling — defaults render in both light and dark modes.
|
||||||
|
|
||||||
|
## Assets
|
||||||
|
|
||||||
|
- Repo-wide assets in `/docs/assets/`; project-scoped assets in the project's own `docs/assets/`.
|
||||||
|
- Prefer **SVG** for diagrams and logos; PNG only for raster screenshots.
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
description: "Use when editing MSBuild files (.csproj, .props, .targets). Covers central package management, artifacts layout, and property inheritance."
|
||||||
|
applyTo: "**/*.{csproj,props,targets}"
|
||||||
|
---
|
||||||
|
# MSBuild Conventions
|
||||||
|
|
||||||
|
## Central Package Management
|
||||||
|
|
||||||
|
All package versions are declared in `Directory.Packages.props` at the repo root. In `.csproj` files:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<!-- Correct -->
|
||||||
|
<PackageReference Include="Newtonsoft.Json" />
|
||||||
|
|
||||||
|
<!-- Wrong — never specify Version -->
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
```
|
||||||
|
|
||||||
|
To add or update a version, edit `Directory.Packages.props`:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
```
|
||||||
|
|
||||||
|
## Properties Set Centrally (Do Not Override)
|
||||||
|
|
||||||
|
These are configured in the root `Directory.Build.props` — do **not** set them in individual projects:
|
||||||
|
|
||||||
|
`LangVersion`, `Nullable`, `ImplicitUsings`.
|
||||||
|
|
||||||
|
## InternalsVisibleTo
|
||||||
|
|
||||||
|
Handled automatically via `<InternalsVisibleToSuffix>` in the root props. Default suffixes are `.Tests` and `Tests`. To add custom visibility:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<ItemGroup>
|
||||||
|
<InternalsVisibleTo Include="MyProject.IntegrationTests" />
|
||||||
|
</ItemGroup>
|
||||||
|
```
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
---
|
||||||
|
description: "Use when adding tracing, metrics, or feature flags: ActivitySource/Meter setup, semantic-convention tags, OTLP exporter config, OpenFeature client usage and flag-key naming."
|
||||||
|
---
|
||||||
|
# Observability & Feature Flags
|
||||||
|
|
||||||
|
## OpenTelemetry
|
||||||
|
|
||||||
|
- One **`ActivitySource`** per logical component, named `Kritikos.<Project>.<Component>`. Declare as `static readonly` on a dedicated `Telemetry` static class within the component (avoid scattering sources across every type).
|
||||||
|
- One **`Meter`** per component, alongside its `ActivitySource`. The names **may** match when both belong to the same component.
|
||||||
|
- Always wrap `StartActivity(...)` in a `using` — leaked activities skew downstream timings.
|
||||||
|
- **Activity names**:
|
||||||
|
- When [OpenTelemetry semantic conventions](https://opentelemetry.io/docs/specs/semconv/) cover the operation (HTTP, DB, messaging, RPC), follow semconv exactly (`HTTP GET`, `db.query`, `messaging.process`).
|
||||||
|
- For custom operations not covered by semconv: `<Verb><Object>` in PascalCase (`ProcessOrder`, `LoadConfiguration`). Avoid generic verbs like `Handle` or `Execute`.
|
||||||
|
- **Tags / attributes**: lowercase dotted, follow semantic conventions where they exist (`http.request.method`, `db.system`, `messaging.destination.name`). Project-specific tags use the `kritikos.<area>.<name>` namespace.
|
||||||
|
- **Metric instruments**: snake_case names with units in the suffix (`orders_processed_total`, `request_duration_seconds`). Always set `unit` and `description` at creation.
|
||||||
|
- **Resource attributes**: when a shared registration helper is added, it should populate `service.name` from `AssemblyName` and `service.version` from the GitVersion-computed `InformationalVersion`. Do not set them manually at call sites.
|
||||||
|
- **Exporter**: OTLP over gRPC, endpoint via `OTEL_EXPORTER_OTLP_ENDPOINT`. Do not register console exporters in `Release` builds.
|
||||||
|
- **Sampling**: parent-based with `TraceIdRatioBased` (1.0 in dev, configurable in prod). Do not set custom samplers without justification.
|
||||||
|
|
||||||
|
## OpenFeature
|
||||||
|
|
||||||
|
- Resolve flags through the configured OpenFeature client (obtained via DI, or `Api.Instance.GetClient()` if no DI integration is wired). Never call provider SDKs directly.
|
||||||
|
- **Flag keys**: `kebab-case`, prefixed by domain (`orders-allow-partial-fulfilment`, `auth-require-mfa`). Keys are stable contracts — treat renames like API breaking changes.
|
||||||
|
- Always pass `defaultValue:` — `client.GetBooleanValue("flag", defaultValue: false, context)`.
|
||||||
|
- **Evaluation context** is built once per request via the configured context provider — do not assemble ad-hoc contexts inline.
|
||||||
|
- Long-lived flags (kill switches, licensing) live in code; short-lived flags (rollouts, experiments) must have a removal date in their description and a tracking issue.
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
---
|
||||||
|
description: "Use when adding, removing, or moving projects, or when editing the solution file or VS Code workspace."
|
||||||
|
applyTo: "*.slnx,*.sln,Solution.code-workspace"
|
||||||
|
---
|
||||||
|
# Solution Conventions
|
||||||
|
|
||||||
|
`Solution.slnx` (XML) is the canonical solution format. The legacy `.sln` is not used; do not regenerate it.
|
||||||
|
|
||||||
|
## Adding & Removing Entries
|
||||||
|
|
||||||
|
Any project, configuration, or asset file added to, removed from, or renamed in a tracked location **must** be reflected in `Solution.slnx` in the same commit. New top-level folders also require an entry in `Solution.code-workspace`.
|
||||||
|
|
||||||
|
Place entries in the virtual folder matching the on-disk location:
|
||||||
|
|
||||||
|
| On-disk location | Virtual folder |
|
||||||
|
| --- | --- |
|
||||||
|
| `src/**`, `samples/**`, `tests/**` (projects + their `Directory.Build.props`) | `/src/`, `/samples/`, `/tests/` |
|
||||||
|
| Repo-root config files (`.editorconfig`, `Directory.*.props`, `GitVersion.yml`, etc.) | `/Configuration/` |
|
||||||
|
| Repo-root assets (`README.md`, `LICENSE.md`, `icon.png`, logos) | `/Assets/` |
|
||||||
|
|
||||||
|
Reserved virtual folder names must not be renamed.
|
||||||
|
|
||||||
|
## Renames
|
||||||
|
|
||||||
|
- Update the `.slnx` entry, the on-disk path, and any `ProjectReference` paths in dependent projects in the same commit.
|
||||||
|
- Never leave dangling `<File Path="…" />` or project entries.
|
||||||
|
|
||||||
|
After any `.slnx` change, run `dotnet build` to confirm all referenced projects load.
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
---
|
||||||
|
description: "Use when creating or modifying test projects under the tests/ folder. Covers naming conventions and structural guardrails."
|
||||||
|
applyTo: "tests/**"
|
||||||
|
---
|
||||||
|
# Test Project Conventions
|
||||||
|
|
||||||
|
Build configuration is handled by `tests/Directory.Build.props` — do not restate its settings.
|
||||||
|
|
||||||
|
## Framework
|
||||||
|
|
||||||
|
- **Testing**: TUnit.
|
||||||
|
- **Mocking**: NSubstitute (analyzers auto-added when referenced).
|
||||||
|
|
||||||
|
## Naming
|
||||||
|
|
||||||
|
- Test project: `<ProjectUnderTest>.Tests` (matches InternalsVisibleTo default).
|
||||||
|
- Test classes: `<ClassUnderTest>Tests`.
|
||||||
|
- Test methods: descriptive names — `MethodName_Condition_ExpectedResult` or similar.
|
||||||
|
|
||||||
|
## Structure
|
||||||
|
|
||||||
|
- Follow **Arrange / Act / Assert**.
|
||||||
|
- Always propose a set of basic tests for new or changed code.
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
---
|
||||||
|
description: "Audit .github/instructions/ and .github/skills/ for duplication, stale references, and unscoped or misscoped files."
|
||||||
|
agent: "agent"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Audit Instructions & Skills
|
||||||
|
|
||||||
|
Walk every file under `.github/instructions/` and `.github/skills/` and produce a prioritised report of issues. Make no edits unless the user approves them after reading the report.
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
### 1. Inventory
|
||||||
|
|
||||||
|
List every `*.instructions.md` and every `**/SKILL.md`, plus `copilot-instructions.md` and any `*.prompt.md`.
|
||||||
|
|
||||||
|
### 2. Per-File Checks
|
||||||
|
|
||||||
|
For each instructions file:
|
||||||
|
|
||||||
|
- `applyTo` glob exists and matches actual files in the repo (no dead globs).
|
||||||
|
- `description` accurately reflects the content (no stale TOCs, no over-promises).
|
||||||
|
- Content is project-specific — flag anything restating universal Markdown / C# / formatter rules, or duplicating the agent runtime (e.g., "work in parallel", "save to memory").
|
||||||
|
- File defers to enforcement layers (`.editorconfig`, analyzers, `Directory.Build.props`) instead of restating their rules.
|
||||||
|
- Cross-references point at files that exist.
|
||||||
|
|
||||||
|
For each skill:
|
||||||
|
|
||||||
|
- Frontmatter `name` matches the directory name.
|
||||||
|
- `description` starts with the action and includes "Use when:".
|
||||||
|
- Procedure steps are actionable, not narration.
|
||||||
|
- Commands actually work against this repo's tool versions and config files.
|
||||||
|
- Cross-skill references use relative paths.
|
||||||
|
|
||||||
|
### 3. Cross-File Checks
|
||||||
|
|
||||||
|
- Same rule defined in multiple files with different wording or severity → flag.
|
||||||
|
- Topics not covered by any file but enforced via PR comments / convention → flag as candidate new file.
|
||||||
|
- `applyTo` overlap that could cause conflicting guidance on a single file → flag.
|
||||||
|
|
||||||
|
### 4. Report
|
||||||
|
|
||||||
|
Produce a table sorted by priority (high / medium / low):
|
||||||
|
|
||||||
|
| Priority | File | Issue | Suggested fix |
|
||||||
|
|
||||||
|
End with two summary counts: total files inspected, total issues found.
|
||||||
|
|
||||||
|
## Guardrails
|
||||||
|
|
||||||
|
- Read-only by default. Apply fixes only if the user explicitly approves them.
|
||||||
|
- When suggesting a fix, quote the exact lines to change so the user can decide without re-reading the file.
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
---
|
||||||
|
description: "Convert an MVC controller to Minimal API endpoints following the project's ASP.NET conventions."
|
||||||
|
agent: "agent"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Convert Controller to Minimal API
|
||||||
|
|
||||||
|
Refactor an MVC controller into Minimal API endpoints aligned with [aspnet-api.instructions.md](../instructions/aspnet-api.instructions.md).
|
||||||
|
|
||||||
|
## Input
|
||||||
|
|
||||||
|
Path to the controller file (e.g., `src/MyApi/Controllers/OrdersController.cs`). Ask if not provided.
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
### 1. Analyse the Controller
|
||||||
|
|
||||||
|
For each action method, capture:
|
||||||
|
|
||||||
|
- HTTP verb and route template.
|
||||||
|
- Parameter binding sources (`[FromRoute]`, `[FromQuery]`, `[FromBody]`, `[FromServices]`).
|
||||||
|
- Return type and possible status codes.
|
||||||
|
- Filters / attributes (`[Authorize]`, `[ProducesResponseType]`, etc.).
|
||||||
|
- Async signature and `CancellationToken` usage.
|
||||||
|
|
||||||
|
### 2. Produce a Migration Plan
|
||||||
|
|
||||||
|
Present a table to the user before writing any code:
|
||||||
|
|
||||||
|
| Action | New endpoint | Notes (auth, filters, response types) |
|
||||||
|
|
||||||
|
Ask for confirmation or adjustments.
|
||||||
|
|
||||||
|
### 3. Generate the Endpoint File
|
||||||
|
|
||||||
|
Create `<Resource>Endpoints.cs` next to the controller, following the conventions:
|
||||||
|
|
||||||
|
- Static class with a `MapXEndpoints(this IEndpointRouteBuilder)` extension.
|
||||||
|
- `MapGroup("/api/v{apiVersion}/{resource}")` with shared `.WithTags(...)`.
|
||||||
|
- Use **`TypedResults`** for every return path.
|
||||||
|
- Use **`[AsParameters]`** for complex parameter sets.
|
||||||
|
- Use **`CancellationToken`** on every async lambda.
|
||||||
|
- Errors return **`ProblemDetails`** via `TypedResults.Problem(...)`.
|
||||||
|
- Endpoint lambdas stay thin; delegate to injected services.
|
||||||
|
|
||||||
|
### 4. Wire Up Registration
|
||||||
|
|
||||||
|
In `Program.cs`, replace `MapControllers()` (or supplement it) with the new `MapXEndpoints()` call. If the controller was the last one, also remove `AddControllers()`.
|
||||||
|
|
||||||
|
### 5. Migrate Tests
|
||||||
|
|
||||||
|
For each test targeting the controller, port it to use `WebApplicationFactory` against the new endpoint. Keep the file name and test names; update the arrange/act sections only.
|
||||||
|
|
||||||
|
### 6. Delete the Controller
|
||||||
|
|
||||||
|
Only after the new endpoints + tests pass. Run `dotnet build` and `dotnet test` before deletion.
|
||||||
|
|
||||||
|
### 7. Update README
|
||||||
|
|
||||||
|
If the project's `README.md` documented the old controller routes, update it in the same commit (per [copilot-instructions.md](../copilot-instructions.md)).
|
||||||
|
|
||||||
|
## Guardrails
|
||||||
|
|
||||||
|
- Do not change behaviour while converting — refactor first, behaviour changes go in a separate commit.
|
||||||
|
- If a controller uses filters or model binders without a Minimal API equivalent, surface the gap and ask before inventing one.
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
---
|
||||||
|
description: "Convert inline logger calls to LoggerMessage-generated partial methods, per the C# conventions."
|
||||||
|
agent: "agent"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Refactor to LoggerMessage
|
||||||
|
|
||||||
|
Replace inline `logger.LogX(...)` calls with `LoggerMessage`-generated `partial` methods, as required by [csharp.instructions.md](../instructions/csharp.instructions.md).
|
||||||
|
|
||||||
|
## Input
|
||||||
|
|
||||||
|
A file or project path. If unspecified, default to the active editor file.
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
### 1. Inventory
|
||||||
|
|
||||||
|
Find every `ILogger.Log*(...)` call site (`LogTrace`, `LogDebug`, `LogInformation`, `LogWarning`, `LogError`, `LogCritical`). Group by containing class.
|
||||||
|
|
||||||
|
### 2. Plan
|
||||||
|
|
||||||
|
For each class with hits, present a table before editing:
|
||||||
|
|
||||||
|
| Method | Level | EventId | Message template | Args |
|
||||||
|
|
||||||
|
Pick stable, sequential `EventId` values per class (start at 1 within the class). Confirm with the user when message templates need to be reworded for clarity.
|
||||||
|
|
||||||
|
### 3. Convert the Class
|
||||||
|
|
||||||
|
- Mark the class `partial`.
|
||||||
|
- Add a nested `static partial class Log` (or top-level partial methods, per existing project style — match what's already in the codebase).
|
||||||
|
- For each call site, generate:
|
||||||
|
```csharp
|
||||||
|
[LoggerMessage(EventId = N, Level = LogLevel.X, Message = "...")]
|
||||||
|
static partial void <Verb><Subject>(ILogger logger, <args>);
|
||||||
|
```
|
||||||
|
- Replace each call site with the new method invocation.
|
||||||
|
- Method names: `PascalCase`, verb-led, third-person (`OrderProcessed`, not `LogOrderProcessed` or `OrderWasProcessed`).
|
||||||
|
|
||||||
|
### 4. Handle Edge Cases
|
||||||
|
|
||||||
|
- **Exceptions**: `Exception` parameter goes first; do not include it in the message template.
|
||||||
|
- **Scopes** (`logger.BeginScope`): leave alone — `LoggerMessage` does not replace scopes.
|
||||||
|
- **Conditional logging** (`if (logger.IsEnabled(...))`): drop the guard; the generated method already checks.
|
||||||
|
|
||||||
|
### 5. Verify
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet build
|
||||||
|
```
|
||||||
|
|
||||||
|
Source generators must produce zero warnings. If a `[LoggerMessage]` definition is rejected, surface the analyzer message and the offending method.
|
||||||
|
|
||||||
|
### 6. Run Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet test
|
||||||
|
```
|
||||||
|
|
||||||
|
Logger-based assertions in tests usually keep working, but message-template changes can break string-matching tests — flag any test failures explicitly.
|
||||||
|
|
||||||
|
## Guardrails
|
||||||
|
|
||||||
|
- Do not change log levels while refactoring — that's a separate decision.
|
||||||
|
- Do not invent new log statements; only convert what already exists.
|
||||||
|
- If a class is `sealed` and has external partial declarations, surface the conflict before adding `partial` to the type.
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
---
|
||||||
|
description: "Create a temporary markdown file summarising all branch changes vs. main/master for PR review"
|
||||||
|
agent: "agent"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Summarize Branch Changes for PR
|
||||||
|
|
||||||
|
Create a temporary markdown file in the repository root called `BRANCH_CHANGES.md` that summarises all changes on the current branch compared to the master/main/default branch. This file is intended to aid PR review and should be deleted before merging.
|
||||||
|
|
||||||
|
## Input
|
||||||
|
|
||||||
|
No explicit input required — the summary is derived from git history and the current Copilot session context.
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
### 1. Gather Git Context
|
||||||
|
|
||||||
|
- Determine the current branch name (`git branch --show-current`).
|
||||||
|
- Find the merge base with `origin/master`.
|
||||||
|
- Collect the commit log between the merge base and HEAD (`git log --oneline`).
|
||||||
|
- Collect the diff stat (`git diff --stat`), file change list (`--diff-filter`), and numstat.
|
||||||
|
|
||||||
|
### 2. Distil Session Requests (if applicable)
|
||||||
|
|
||||||
|
If Copilot session context is available, extract the key user requests that drove the changes and present them as a bullet-point list at the top of the file under a **Copilot Session Requests** heading.
|
||||||
|
|
||||||
|
### 3. Produce the Markdown File
|
||||||
|
|
||||||
|
Create `BRANCH_CHANGES.md` in the repository root with the following sections:
|
||||||
|
|
||||||
|
#### Header
|
||||||
|
|
||||||
|
- Branch name, base branch, and current date.
|
||||||
|
|
||||||
|
#### Copilot Session Requests
|
||||||
|
|
||||||
|
- Bullet list of the user prompts/requests from the current session that led to changes (omit if no session context).
|
||||||
|
|
||||||
|
#### Commits
|
||||||
|
|
||||||
|
- Table with columns: Hash, Message, Author, Date.
|
||||||
|
|
||||||
|
#### Files Changed
|
||||||
|
|
||||||
|
- Table with columns: File, Change type (Added/Modified/Deleted), Insertions, Deletions.
|
||||||
|
- Summary line: _N files changed, X insertions, Y deletions._
|
||||||
|
|
||||||
|
#### Change Details
|
||||||
|
|
||||||
|
- One sub-heading per changed file (or logical group of related files).
|
||||||
|
- Numbered list of the distinct changes made, written for a reviewer who is unfamiliar with the recent context.
|
||||||
|
|
||||||
|
#### Pending Session Work (if applicable)
|
||||||
|
|
||||||
|
- Any in-progress or uncommitted work from the current Copilot session that has not yet been committed.
|
||||||
|
|
||||||
|
## Guidelines
|
||||||
|
|
||||||
|
- Keep descriptions concise but specific — a reviewer should understand _what_ changed and _why_ without reading the diff.
|
||||||
|
- Use git data as the source of truth; supplement with session context only for intent and motivation.
|
||||||
|
- Do not include the full diff content — summarise it.
|
||||||
|
- Mark the file clearly as temporary (mention it should be deleted before merge).
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
---
|
||||||
|
description: "Sync the current repository with upstream changes from kritikos-io/templates-dotnet, with conflict-resolution guidance."
|
||||||
|
agent: "agent"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Sync From Template
|
||||||
|
|
||||||
|
Pull updates from the upstream `kritikos-io/templates-dotnet` repository, following the workflow documented in the root `README.md`.
|
||||||
|
|
||||||
|
## Steps
|
||||||
|
|
||||||
|
### 1. Verify the `template` Remote
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git remote -v | grep template
|
||||||
|
```
|
||||||
|
|
||||||
|
If absent, add it and warn the user that the first sync requires `--allow-unrelated-histories`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git remote add template https://github.com/kritikos-io/templates-dotnet
|
||||||
|
git fetch --all
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Check Working Tree
|
||||||
|
|
||||||
|
`git status` must be clean. If it isn't, stop and ask the user to commit or stash before continuing.
|
||||||
|
|
||||||
|
### 3. Pull
|
||||||
|
|
||||||
|
- **First-time sync** (template remote was just added):
|
||||||
|
```bash
|
||||||
|
git merge template/main --allow-unrelated-histories
|
||||||
|
```
|
||||||
|
- **Subsequent syncs**:
|
||||||
|
```bash
|
||||||
|
git pull template main
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Resolve Conflicts
|
||||||
|
|
||||||
|
Common conflict zones, with resolution guidance:
|
||||||
|
|
||||||
|
| File / area | Strategy |
|
||||||
|
| --- | --- |
|
||||||
|
| `Solution.slnx`, `Solution.code-workspace` | Keep local — these are project-specific. Re-apply any new entries from upstream manually. |
|
||||||
|
| `Directory.Build.props`, `Directory.Build.targets`, `Directory.Packages.props` | Take upstream as the base, re-apply project-specific overrides on top. |
|
||||||
|
| `.github/instructions/`, `.github/skills/`, `.github/prompts/` | Take upstream; project-specific guidance should live in a *separate* file, never as edits to template-shipped files. |
|
||||||
|
| `README.md`, `LICENSE.md`, `icon.png` | Keep local — these are project-specific. |
|
||||||
|
| `docker/Dockerfile` | Take upstream; project-specific compose lives in `docker/compose.*.yaml`. |
|
||||||
|
|
||||||
|
When a conflict needs human judgement, list it with file path + decision options rather than guessing.
|
||||||
|
|
||||||
|
### 5. Verify
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet restore --force-evaluate
|
||||||
|
dotnet build
|
||||||
|
dotnet test
|
||||||
|
```
|
||||||
|
|
||||||
|
If lock files moved, commit `packages.lock.json` updates.
|
||||||
|
|
||||||
|
### 6. Commit
|
||||||
|
|
||||||
|
Use a single merge commit; do not squash. Subject:
|
||||||
|
|
||||||
|
```
|
||||||
|
🔀 Syncs with kritikos-io/templates-dotnet
|
||||||
|
```
|
||||||
|
|
||||||
|
(Per [copilot-commit-message-instructions.md](../copilot-commit-message-instructions.md): gitmoji, third-person imperative.)
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
---
|
||||||
|
name: docker-build
|
||||||
|
description: "Build, test, publish, or pack .NET projects using the multi-stage Docker pipeline. Use when: building Docker images, running containerized tests, creating migration bundles, publishing to containers, or troubleshooting Dockerfile stages."
|
||||||
|
argument-hint: "Describe what you want to build or publish (e.g., 'publish WebApplication1 as web app')"
|
||||||
|
---
|
||||||
|
# Docker Build Skill
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- Build and run a .NET project in Docker
|
||||||
|
- Run tests inside a container
|
||||||
|
- Create a NuGet package via Docker
|
||||||
|
- Create an EF Core migration bundle
|
||||||
|
- Troubleshoot multi-stage Docker build issues
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Docker Desktop or Docker Engine running
|
||||||
|
- Repository root as build context
|
||||||
|
|
||||||
|
## Common Workflows
|
||||||
|
|
||||||
|
### Build and run a web application
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker compose -f docker/compose.sample.yaml build sample-api \
|
||||||
|
--build-arg PUBLISHED_PROJECT=<ProjectName>
|
||||||
|
docker compose -f docker/compose.sample.yaml up sample-api
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build self-contained application
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker build -f docker/Dockerfile \
|
||||||
|
--target final \
|
||||||
|
--build-arg RUNTIME_BASE=self-contained \
|
||||||
|
--build-arg PUBLISHED_PROJECT=<ProjectName> \
|
||||||
|
-t myapp .
|
||||||
|
```
|
||||||
|
|
||||||
|
### Run tests in container
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker build -f docker/Dockerfile --target test .
|
||||||
|
```
|
||||||
|
|
||||||
|
### Lint OpenAPI documents
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker build -f docker/Dockerfile --target openapi-lint .
|
||||||
|
```
|
||||||
|
|
||||||
|
### Pack NuGet packages
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker build -f docker/Dockerfile --target pack --output artifacts/nuget .
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create EF Core migration bundle
|
||||||
|
|
||||||
|
```shell
|
||||||
|
docker build -f docker/Dockerfile --target migrations \
|
||||||
|
--build-arg PUBLISHED_PROJECT=<StartupProject> \
|
||||||
|
--build-arg DATABASE_PROJECT=<EFProject> \
|
||||||
|
--build-arg DBCONTEXT=<OptionalContextName> \
|
||||||
|
-t migrations .
|
||||||
|
```
|
||||||
|
|
||||||
|
## Stage Reference
|
||||||
|
|
||||||
|
See [Dockerfile](../../docker/Dockerfile) for the full multi-stage pipeline. Key stages and their targets:
|
||||||
|
|
||||||
|
| `--target` | Produces |
|
||||||
|
|------------|----------|
|
||||||
|
| `test` | Runs `dotnet test` — exits non-zero on failure |
|
||||||
|
| `openapi-lint` | Spectral lint on generated OpenAPI JSON |
|
||||||
|
| `publish` | Published app in `/app/publish` |
|
||||||
|
| `pack` | NuGet `.nupkg` files in `/app/publish` |
|
||||||
|
| `migration-bundle` | Standalone EF migration binary |
|
||||||
|
| `final` | Production runtime image |
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
- **Restore failures**: Check `nuget.config` package sources and ensure `packages.lock.json` files are committed.
|
||||||
|
- **GitVersion errors**: The `gitversion` stage needs `.git/` — ensure the build context includes it.
|
||||||
|
- **Missing OpenAPI docs**: The `openapi-lint` stage only runs Spectral if `*.json` files exist in `artifacts/OpenApi/`.
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
---
|
||||||
|
name: ef-migration
|
||||||
|
description: 'Add, remove, or apply Entity Framework Core migrations against a project under src/. Use when: creating a new migration, reverting the last migration, generating a migration bundle, applying migrations to a database.'
|
||||||
|
argument-hint: 'Describe the schema change (e.g., "add audit columns to Orders") and the target DbContext if multiple exist'
|
||||||
|
---
|
||||||
|
|
||||||
|
# EF Core Migration
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- The EF project (containing the `DbContext`) is referenced by — or is itself — a runnable startup project.
|
||||||
|
- Requires `dotnet ef`: `dotnet tool restore` (if a manifest exists) or `dotnet tool install -g dotnet-ef`.
|
||||||
|
|
||||||
|
## Conventions
|
||||||
|
|
||||||
|
- **Migration name**: `PascalCase`, imperative, third person, ≤ 60 chars (e.g., `AddsOrderAuditColumns`, not `audit_changes` or `Migration1`).
|
||||||
|
- **Output folder**: default `Migrations/` inside the EF project. Do not relocate.
|
||||||
|
- **One DbContext per command** — pass `--context` whenever the project has more than one.
|
||||||
|
- **Never edit a migration after it has been applied to a shared environment.** Add a corrective migration instead.
|
||||||
|
- **Commit migrations together with the model change** that produced them.
|
||||||
|
|
||||||
|
## Procedure
|
||||||
|
|
||||||
|
The **EF project** contains the `DbContext`; the **startup project** is the runnable project EF executes against (usually a web/worker referencing the EF project).
|
||||||
|
|
||||||
|
1. **Add the migration:**
|
||||||
|
```bash
|
||||||
|
dotnet ef migrations add <PascalCaseName> \
|
||||||
|
--project src/<EFProject> \
|
||||||
|
--startup-project src/<StartupProject> \
|
||||||
|
--context <DbContextName>
|
||||||
|
```
|
||||||
|
2. **Inspect** the generated `*.cs` and `*.Designer.cs` files for unintended changes (unrelated columns, dropped indices).
|
||||||
|
3. **If wrong, remove before committing:**
|
||||||
|
```bash
|
||||||
|
dotnet ef migrations remove --project src/<EFProject> --startup-project src/<StartupProject>
|
||||||
|
```
|
||||||
|
|
||||||
|
For a deployable migration binary, use the [docker-build](../docker-build/SKILL.md) skill's `migrations` target.
|
||||||
|
|
||||||
|
## Generating an SQL Script
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet ef migrations script <FromMigration> <ToMigration> \
|
||||||
|
--project src/<EFProject> \
|
||||||
|
--startup-project src/<StartupProject> \
|
||||||
|
--idempotent \
|
||||||
|
--output artifacts/migrations.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `--idempotent` whenever the script may run against a database in an unknown state.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
- **"Unable to create a 'DbContext'…"** — pass `--startup-project` explicitly; auto-detection picks the wrong project in multi-project solutions.
|
||||||
|
- **Multiple DbContexts found** — pass `--context <Name>`.
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
---
|
||||||
|
status: proposed
|
||||||
|
date: YYYY-MM-DD
|
||||||
|
decision-makers: [names or roles]
|
||||||
|
# consulted: [subject-matter experts with two-way communication]
|
||||||
|
# informed: [stakeholders kept up-to-date with one-way communication]
|
||||||
|
---
|
||||||
|
# NNNN. {short title, representative of solved problem and found solution}
|
||||||
|
|
||||||
|
## Context and Problem Statement
|
||||||
|
|
||||||
|
{Describe the context and problem statement in two to three sentences, or as a short illustrative story. Articulate the problem as a question if helpful, and link to issues, PRs, or discussions.}
|
||||||
|
|
||||||
|
## Decision Drivers
|
||||||
|
|
||||||
|
- {decision driver 1, e.g., a force, facing concern, quality attribute}
|
||||||
|
- {decision driver 2}
|
||||||
|
- …
|
||||||
|
|
||||||
|
## Considered Options
|
||||||
|
|
||||||
|
- {title of option 1}
|
||||||
|
- {title of option 2}
|
||||||
|
- {title of option 3}
|
||||||
|
- …
|
||||||
|
|
||||||
|
## Decision Outcome
|
||||||
|
|
||||||
|
Chosen option: **"{title of option X}"**, because {justification — e.g., the only option meeting a k.o. criterion, resolves driver {driver}, or comes out best in the comparison below}.
|
||||||
|
|
||||||
|
### Consequences
|
||||||
|
|
||||||
|
- Good, because {positive consequence}.
|
||||||
|
- Bad, because {negative consequence / accepted trade-off}.
|
||||||
|
- Follow-up: {action item, if any}.
|
||||||
|
|
||||||
|
<!-- Optional. Remove if not used. -->
|
||||||
|
### Confirmation
|
||||||
|
|
||||||
|
{How will compliance with this ADR be confirmed? E.g., a design/code review, an ArchUnit test, a CI check, or a follow-up audit.}
|
||||||
|
|
||||||
|
<!-- Optional. Remove if not used. -->
|
||||||
|
## Pros and Cons of the Options
|
||||||
|
|
||||||
|
### Comparison
|
||||||
|
|
||||||
|
| Driver | {Option 1} | {Option 2} | {Option 3} |
|
||||||
|
| ---------- | ---------- | ---------- | ---------- |
|
||||||
|
| {driver 1} | Yes | Maybe | No |
|
||||||
|
| {driver 2} | No | Yes | Yes |
|
||||||
|
|
||||||
|
### {title of option 1}
|
||||||
|
|
||||||
|
{example | description | pointer to more information}
|
||||||
|
|
||||||
|
- Good, because {argument}.
|
||||||
|
- Neutral, because {argument}.
|
||||||
|
- Bad, because {argument}.
|
||||||
|
|
||||||
|
### {title of option 2}
|
||||||
|
|
||||||
|
{example | description | pointer to more information}
|
||||||
|
|
||||||
|
- Good, because {argument}.
|
||||||
|
- Bad, because {argument}.
|
||||||
|
|
||||||
|
<!-- Optional. Remove if not used. -->
|
||||||
|
## More Information
|
||||||
|
|
||||||
|
{Additional evidence/confidence for the decision, team agreement notes, when/how to revisit, links to related ADRs and resources.}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
---
|
||||||
|
name: new-adr
|
||||||
|
description: 'Create a new Architectural Decision Record (ADR) capturing a justified design choice that addresses an architecturally significant functional or non-functional requirement. Use when: creating a new ADR, documenting an architectural choice, recording a design decision, superseding a previous decision, capturing rationale for a framework/library/pattern selection.'
|
||||||
|
argument-hint: 'Brief description of the decision (e.g., "adopt Minimal APIs over MVC controllers")'
|
||||||
|
---
|
||||||
|
# New Architectural Decision Record
|
||||||
|
|
||||||
|
You are assisting the user in producing a well-structured, comprehensive ADR. Ask clarifying questions, offer suggestions and examples, and ensure the record follows the standard format with all required sections filled.
|
||||||
|
|
||||||
|
Reference: <https://adr.github.io>.
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- A design choice has a **measurable effect on architecture or quality attributes** (security, performance, scalability, maintainability, cost, DX).
|
||||||
|
- The decision is **non-obvious**, has **trade-offs**, or **supersedes** prior guidance.
|
||||||
|
- A reviewer or future maintainer would reasonably ask *"why did we do it this way?"*.
|
||||||
|
|
||||||
|
**Not an ADR**: cosmetic refactors, bug fixes, style preferences, or decisions with no viable alternatives. Use a commit message or code comment instead.
|
||||||
|
|
||||||
|
## Location & Filename
|
||||||
|
|
||||||
|
- **Folder**: `docs/adr/`
|
||||||
|
- **Filename**: `NNNN-kebab-title.md` (zero-padded, four digits, sequential; e.g., `0001-use-minimal-apis.md`).
|
||||||
|
- **Index** (optional): `docs/adr/README.md` listing all ADRs with status.
|
||||||
|
|
||||||
|
Determine the next `NNNN` by scanning existing files and incrementing the highest number. Never reuse numbers, even for retracted ADRs.
|
||||||
|
|
||||||
|
## Required Sections
|
||||||
|
|
||||||
|
Every ADR must include these MADR sections, in order:
|
||||||
|
|
||||||
|
1. **Context and Problem Statement** — the situation, goals, and constraints that frame the decision; pose the problem as a question when helpful.
|
||||||
|
2. **Decision Drivers** — bullet list of forces, concerns, and quality attributes that matter.
|
||||||
|
3. **Considered Options** — bullet list of viable alternatives.
|
||||||
|
4. **Decision Outcome** — the chosen option, justification, nested **Consequences** (good/bad/follow-up), and optional **Confirmation** subsection.
|
||||||
|
|
||||||
|
MADR-optional sections (include when they add value):
|
||||||
|
|
||||||
|
- **Pros and Cons of the Options** — per-option Good/Neutral/Bad bullets. Prefix with the comparison table below when more than two options compete.
|
||||||
|
- **More Information** — links, revisit notes, related ADRs.
|
||||||
|
|
||||||
|
### Comparison Table (project addition)
|
||||||
|
|
||||||
|
When using **Pros and Cons of the Options**, lead with a Yes/No/Maybe matrix scoring each option against each driver. This is a project convention on top of MADR, not part of the spec, but it forces explicit comparison and exposes weak options.
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
| Driver | Option A | Option B | Option C |
|
||||||
|
| ---------- | -------- | -------- | -------- |
|
||||||
|
| {driver 1} | Yes | Maybe | No |
|
||||||
|
| {driver 2} | No | Yes | Yes |
|
||||||
|
```
|
||||||
|
|
||||||
|
## Status Lifecycle
|
||||||
|
|
||||||
|
`proposed` → `accepted` → (`deprecated` | `superseded by ADR-NNNN`) · `rejected` is terminal from `proposed`.
|
||||||
|
|
||||||
|
- New ADRs start as `proposed` unless the user confirms acceptance.
|
||||||
|
- When superseding, **update the old ADR's status** to `superseded by ADR-NNNN` and add a back-link. Never rewrite history of an accepted ADR.
|
||||||
|
- `date` reflects the last status change.
|
||||||
|
|
||||||
|
## MADR Template
|
||||||
|
|
||||||
|
This skill follows the [MADR 4.0](https://adr.github.io/madr/) (Markdown Any Decision Records) format with one project addition (see *Comparison Table* above). Copy [MADR.md](MADR.md) to `docs/adr/NNNN-kebab-title.md` and fill in the placeholders. The folder `docs/adr/` is a project convention; MADR's own recommendation is `docs/decisions/`.
|
||||||
|
|
||||||
|
## Procedure
|
||||||
|
|
||||||
|
1. **Confirm significance.** Check against the "When to Use" criteria. If it doesn't qualify, suggest a lighter alternative (code comment, PR description, CHANGELOG entry) and stop.
|
||||||
|
2. **Assign a number.** List `docs/adr/` and pick the next `NNNN`.
|
||||||
|
3. **Interview the user — one section at a time.** Ask focused questions for the current section, offer suggestions/examples where useful, then move on. Do not dump every question at once.
|
||||||
|
4. **Show progress** after each section using a status table with these markers:
|
||||||
|
- ✔️ completed
|
||||||
|
- 🟡 in progress
|
||||||
|
- ➖ not started
|
||||||
|
|
||||||
|
```markdown
|
||||||
|
| Section | Status |
|
||||||
|
| ----------------------------- | ------ |
|
||||||
|
| Context and Problem Statement | ✔️ |
|
||||||
|
| Decision Drivers | 🟡 |
|
||||||
|
| Considered Options | ➖ |
|
||||||
|
| Decision Outcome | ➖ |
|
||||||
|
| Consequences | ➖ |
|
||||||
|
| Pros and Cons (optional) | ➖ |
|
||||||
|
```
|
||||||
|
|
||||||
|
5. **Draft the ADR** as sections are filled. Keep the title short and decision-oriented (`"Use X for Y"` or `"Adopt X over Y"`). Status = `proposed` unless the user confirms acceptance.
|
||||||
|
6. **Handle supersession.** If this ADR replaces another, update the predecessor's frontmatter `status` to `superseded by ADR-NNNN` and add a cross-link in its body.
|
||||||
|
7. **Update index.** If `docs/adr/README.md` exists, append the new entry with status; otherwise offer to create one.
|
||||||
|
8. **Save & confirm.** Write the file to `docs/adr/NNNN-kebab-title.md`, validate frontmatter YAML and filename, and confirm the saved path back to the user.
|
||||||
|
|
||||||
|
## Quality Bar
|
||||||
|
|
||||||
|
- **Title states the decision**, not the topic. ✅ `Use Minimal APIs for new endpoints` · ❌ `API style`.
|
||||||
|
- **Options are real alternatives** that were genuinely considered — not strawmen.
|
||||||
|
- **Consequences include the downsides** we accept. An ADR with only positives is incomplete.
|
||||||
|
- **Links > prose** for context already documented elsewhere (issues, RFCs, benchmarks).
|
||||||
|
- **Immutable once accepted.** Further changes happen via a new ADR that supersedes.
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
---
|
||||||
|
name: new-library
|
||||||
|
description: 'Scaffold a new reusable .NET library with correct naming, multi-targeting, and structure. Use when: creating a new library project, adding a reusable package, setting up a shared library under src/.'
|
||||||
|
argument-hint: 'Brief description of the library purpose (e.g., "hashing utilities", "EF Core auditing")'
|
||||||
|
---
|
||||||
|
|
||||||
|
# New Library
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- Creating a new reusable, packable library under `src/`
|
||||||
|
- Adding a shared component meant for NuGet distribution
|
||||||
|
|
||||||
|
## Naming Convention
|
||||||
|
|
||||||
|
Libraries use a `{Domain}.{Feature}` pattern. The `Kritikos.` root namespace prefix is applied automatically by `Directory.Build.props`.
|
||||||
|
|
||||||
|
| Domain prefix | When to use | Example |
|
||||||
|
|---|---|---|
|
||||||
|
| `AspNetCore.{Feature}` | Depends on `Microsoft.AspNetCore.App` | `AspNetCore.ProblemDetails` |
|
||||||
|
| `Extensions.{Feature}` | Framework-agnostic, depends only on `Microsoft.Extensions.*` | `Extensions.Hashing` |
|
||||||
|
| `EntityFrameworkCore.{Feature}` | Depends on EF Core | `EntityFrameworkCore.Auditing` |
|
||||||
|
| *(no prefix)* | Pure .NET with no framework dependency | `Primitives` |
|
||||||
|
|
||||||
|
**Always propose 2–4 name options** to the user and allow a custom choice.
|
||||||
|
|
||||||
|
## Multi-Targeting
|
||||||
|
|
||||||
|
Target **both current LTS versions** plus optionally **one STS version** if newer than the latest LTS:
|
||||||
|
|
||||||
|
| Scenario | Targets | Rationale |
|
||||||
|
|---|---|---|
|
||||||
|
| .NET 10 is current LTS | `net8.0;net10.0` | Skip .NET 9 (STS, superseded) |
|
||||||
|
| .NET 11 (STS) ships | `net8.0;net10.0;net11.0` | 11 > 10, include it |
|
||||||
|
| .NET 12 (LTS) ships | `net10.0;net12.0` | .NET 8 drops; 11 superseded |
|
||||||
|
|
||||||
|
Libraries with **no framework dependency** (no domain prefix) should also target `netstandard2.0`/`netstandard2.1` when APIs and dependencies allow. Framework-dependent libraries skip .NET Standard.
|
||||||
|
|
||||||
|
## Procedure
|
||||||
|
|
||||||
|
1. Ask the user for the library's purpose.
|
||||||
|
2. Propose name options using the naming table above.
|
||||||
|
3. Determine the correct multi-targeting based on current LTS/STS and framework dependencies.
|
||||||
|
4. Create the project under `src/{LibraryName}/`.
|
||||||
|
5. Do **not** specify `Version` on `PackageReference` — add versions in `Directory.Packages.props`.
|
||||||
|
6. Create a matching test project under `tests/{LibraryName}.Tests/`.
|
||||||
|
7. Add both projects to `Solution.slnx`.
|
||||||
|
8. Verify the build compiles cleanly.
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
---
|
||||||
|
name: new-release
|
||||||
|
description: 'Cut a new release: tag the appropriate commit, generate the changelog, and produce build artifacts. Use when: releasing a new version, tagging a release, publishing NuGet packages, preparing release artifacts.'
|
||||||
|
argument-hint: 'Branch or commit to release from (default: current main) and the kind of release (stable, prerelease, hotfix)'
|
||||||
|
---
|
||||||
|
|
||||||
|
# New Release
|
||||||
|
|
||||||
|
Versioning is **GitVersion-driven** (`GitVersion.yml`). Do not hand-pick versions — let GitVersion compute them from branch and tag history.
|
||||||
|
|
||||||
|
## Versioning
|
||||||
|
|
||||||
|
| Branch | Label | Resulting version |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `main` | — | `MAJOR.MINOR.PATCH` (stable) |
|
||||||
|
| `develop` / `dev` / `development` | `beta` | `MAJOR.MINOR.PATCH-beta.N` |
|
||||||
|
| `release/*`, `hotfix/*`, `feature/*` | branch name | `…-<branch>.N` |
|
||||||
|
|
||||||
|
- Tags use the prefix `v` (regex `[vV]?` also accepts `V` or none).
|
||||||
|
- Only changes under `src/`, `Directory.Packages.props`, or `GitVersion.yml` increment the version.
|
||||||
|
- Increments are suppressed for already-merged branches and already-tagged commits.
|
||||||
|
|
||||||
|
## Procedure
|
||||||
|
|
||||||
|
1. **Sync.** `git fetch --all --tags && git status` — confirm clean.
|
||||||
|
2. **Compute.** `dotnet build -getProperty:Version` — verify the value matches expectations.
|
||||||
|
3. **Pack.** `dotnet pack -c Release` (or use the [docker-build](../docker-build/SKILL.md) `pack` target). Artifacts land in `artifacts/nuget/`.
|
||||||
|
4. **Tag.** `git tag -a v<version> -m "Release v<version>" && git push origin v<version>`.
|
||||||
|
5. **Publish** packages to the configured feed.
|
||||||
|
6. **Create the GitHub release** linked to the tag, using the generated changelog as notes.
|
||||||
|
|
||||||
|
For hotfixes: branch from the latest stable tag (`git switch -c hotfix/<name> v<latest-stable>`), follow the procedure, then back-merge into `main` and `develop`.
|
||||||
|
|
||||||
|
## Guardrails
|
||||||
|
|
||||||
|
- **Tags are immutable** once pushed; never move or delete them.
|
||||||
|
- **Never skip a `PATCH`** — ship a fix forward.
|
||||||
|
- **Do not edit `GitVersion.yml` to force a version.** Address the underlying cause (missing tag, branch base, path filter, commit messages).
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
---
|
||||||
|
name: new-web-api-project
|
||||||
|
description: 'Scaffold a new ASP.NET web project (API or worker service) with correct structure, launch settings, and Docker integration. Use when: creating a new web API, adding an ASP.NET project, setting up a new web service under src/.'
|
||||||
|
argument-hint: 'Brief description of the web project (e.g., "REST API for user management", "background worker for email processing")'
|
||||||
|
---
|
||||||
|
|
||||||
|
# New Web Project
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- Creating a new ASP.NET web API or worker service under `src/`
|
||||||
|
- Adding a web project that will be deployed via Docker
|
||||||
|
|
||||||
|
## Procedure
|
||||||
|
|
||||||
|
1. Ask the user for the project's purpose and type (API or worker).
|
||||||
|
2. Create the project under `src/{ProjectName}/` using the appropriate SDK (`Microsoft.NET.Sdk.Web` or `Microsoft.NET.Sdk.Worker`).
|
||||||
|
4. **Single target framework** — web projects target only the current LTS (no multi-targeting).
|
||||||
|
5. Create `Properties/launchSettings.json` with `http` and `https` profiles:
|
||||||
|
- Pick ports that **do not conflict** with existing projects — check all `src/*/Properties/launchSettings.json` files first.
|
||||||
|
- Set `launchBrowser: false`.
|
||||||
|
- Set `ASPNETCORE_ENVIRONMENT: Development`.
|
||||||
|
6. For APIs: use **Minimal APIs** with OpenAPI support (`Microsoft.AspNetCore.OpenApi`). The OpenAPI document generation and Spectral linting are handled automatically by the build infrastructure.
|
||||||
|
7. Create a matching test project under `tests/{ProjectName}.Tests/`.
|
||||||
|
8. Add both projects to `Solution.slnx`.
|
||||||
|
9. Add a compose service entry to `compose.yaml` (or create one from `docker/compose.sample.yaml`):
|
||||||
|
- Set `RUNTIME_BASE: web` for APIs, `RUNTIME_BASE: app` for workers.
|
||||||
|
- Set `PUBLISHED_PROJECT` to the project name.
|
||||||
|
- Build context is the repo root with `dockerfile: docker/Dockerfile`.
|
||||||
|
10. Verify the build compiles cleanly.
|
||||||
|
|
||||||
|
## Launch Settings Template
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/launchsettings.json",
|
||||||
|
"profiles": {
|
||||||
|
"http": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": false,
|
||||||
|
"applicationUrl": "http://localhost:{HTTP_PORT}",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"https": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"dotnetRunMessages": true,
|
||||||
|
"launchBrowser": false,
|
||||||
|
"applicationUrl": "https://localhost:{HTTPS_PORT};http://localhost:{HTTP_PORT}",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
+2
-1
@@ -3,10 +3,11 @@ is_global = true
|
|||||||
# Ruleset replacement
|
# Ruleset replacement
|
||||||
# C# compiler diagnostics
|
# C# compiler diagnostics
|
||||||
dotnet_diagnostic.CS1573.severity = none # Missing XML comment for parameter
|
dotnet_diagnostic.CS1573.severity = none # Missing XML comment for parameter
|
||||||
dotnet_diagnostic.CS1591.severity = none # Missing XML comment for publicly visible type or member
|
dotnet_diagnostic.CS1591.severity = suggestion # Missing XML comment for publicly visible type or member
|
||||||
dotnet_diagnostic.CS2008.severity = none # No source files specified
|
dotnet_diagnostic.CS2008.severity = none # No source files specified
|
||||||
|
|
||||||
# Code quality analyzers
|
# Code quality analyzers
|
||||||
|
dotnet_diagnostic.CA1515.severity = suggestion # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1515
|
||||||
dotnet_diagnostic.CA1303.severity = none # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1303
|
dotnet_diagnostic.CA1303.severity = none # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1303
|
||||||
dotnet_diagnostic.CA1707.severity = none # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1707
|
dotnet_diagnostic.CA1707.severity = none # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1707
|
||||||
dotnet_diagnostic.CA1848.severity = none # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1848
|
dotnet_diagnostic.CA1848.severity = none # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1848
|
||||||
|
|||||||
Vendored
+10
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"EditorConfig.EditorConfig",
|
||||||
|
"mhutchie.git-graph",
|
||||||
|
"ms-dotnettools.csdevkit",
|
||||||
|
"ms-vscode-remote.remote-containers",
|
||||||
|
"seatonjiang.gitmoji-vscode",
|
||||||
|
"redhat.vscode-xml"
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+20
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"json.schemas": [
|
||||||
|
{
|
||||||
|
"fileMatch": [
|
||||||
|
"xunit.runner.json"
|
||||||
|
],
|
||||||
|
"url": "https://xunit.net/schema/current/xunit.runner.schema.json"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fileMatch": [
|
||||||
|
"stylecop.json"
|
||||||
|
],
|
||||||
|
"url": "https://raw.githubusercontent.com/bjornhellander/NewStyleCopAnalyzers/refs/heads/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"editor.wordWrap": "on",
|
||||||
|
"[xml]": {
|
||||||
|
"editor.defaultFormatter": "redhat.vscode-xml"
|
||||||
|
}
|
||||||
|
}
|
||||||
+10
-6
@@ -9,7 +9,7 @@
|
|||||||
<!-- Suppresses display of the sign-on banner -->
|
<!-- Suppresses display of the sign-on banner -->
|
||||||
<NoLogo>true</NoLogo>
|
<NoLogo>true</NoLogo>
|
||||||
<!-- Prepend organization name to default namespace -->
|
<!-- Prepend organization name to default namespace -->
|
||||||
<RootNamespace>Cognify.$(MSBuildProjectName)</RootNamespace>
|
<RootNamespace>Kritikos.$(MSBuildProjectName)</RootNamespace>
|
||||||
<!-- Enable global usings based on project type -->
|
<!-- Enable global usings based on project type -->
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<!-- Generate documentation file and ignore warnings for undocumented elements -->
|
<!-- Generate documentation file and ignore warnings for undocumented elements -->
|
||||||
@@ -49,8 +49,13 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- Defaults to checked context for math operations, throws OverflowException when needed -->
|
<!-- Defaults to unchecked context for math operations for performance -->
|
||||||
<CheckForOverflowUnderflow>true</CheckForOverflowUnderflow>
|
<!-- set to true to throws OverflowException when needed -->
|
||||||
|
<CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Label="OpenApi Source Generated Interceptors">
|
||||||
|
<InterceptorsNamespaces>$(InterceptorsNamespaces);Microsoft.AspNetCore.OpenApi.Generated</InterceptorsNamespaces>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="$(ArtifactsPath) == '' AND $(DisableCustomArtifactsPath) != 'true'">
|
<PropertyGroup Condition="$(ArtifactsPath) == '' AND $(DisableCustomArtifactsPath) != 'true'">
|
||||||
@@ -163,11 +168,10 @@
|
|||||||
|
|
||||||
<PropertyGroup Label="Package">
|
<PropertyGroup Label="Package">
|
||||||
<PackageId>$(RootNamespace)</PackageId>
|
<PackageId>$(RootNamespace)</PackageId>
|
||||||
<Company>Cognify</Company>
|
<Company>Kritikos IO</Company>
|
||||||
<Authors>Elisa Servidio, Dimitrios Tsapetis, Alexandros Kritikos, Stefanos Katsikas, Katerina Pouspourika, Antonia Tsatsouli</Authors>
|
<Authors>Alexandros Kritikos</Authors>
|
||||||
<CurrentYear>$([System.DateTime]::Now.ToString(yyyy))</CurrentYear>
|
<CurrentYear>$([System.DateTime]::Now.ToString(yyyy))</CurrentYear>
|
||||||
<Copyright>Copyright © 2017-$(CurrentYear) Kritikos IO. All rights reserved.</Copyright>
|
<Copyright>Copyright © 2017-$(CurrentYear) Kritikos IO. All rights reserved.</Copyright>
|
||||||
<Copyright>Copyright © 2024-$(CurrentYear) Cognify. All rights reserved.</Copyright>
|
|
||||||
<PackageIcon Condition="$(ProjectIconExists) == 'True'">icon.png</PackageIcon>
|
<PackageIcon Condition="$(ProjectIconExists) == 'True'">icon.png</PackageIcon>
|
||||||
<PackageReadmeFile Condition="$(ProjectReadMeExists) == 'True'">README.md</PackageReadmeFile>
|
<PackageReadmeFile Condition="$(ProjectReadMeExists) == 'True'">README.md</PackageReadmeFile>
|
||||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<Project>
|
<Project>
|
||||||
<ItemGroup Label="Packages">
|
<ItemGroup Label="Packages">
|
||||||
<PackageVersion Include="GitVersion.MsBuild" Version="6.6.2" />
|
<PackageVersion Include="GitVersion.MsBuild" Version="6.7.0" />
|
||||||
<PackageVersion Include="Microsoft.Sbom.Targets" Version="4.1.5" />
|
<PackageVersion Include="Microsoft.Sbom.Targets" Version="4.1.5" />
|
||||||
<PackageVersion Include="NewStyleCop.Analyzers" Version="1.2.1" />
|
<PackageVersion Include="NewStyleCop.Analyzers" Version="1.2.1" />
|
||||||
<PackageVersion Include="NSubstitute.Analyzers.CSharp" Version="1.0.17" />
|
<PackageVersion Include="NSubstitute.Analyzers.CSharp" Version="1.0.17" />
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ branches:
|
|||||||
mode: ContinuousDelivery
|
mode: ContinuousDelivery
|
||||||
source-branches:
|
source-branches:
|
||||||
- develop
|
- develop
|
||||||
|
- main
|
||||||
hotfix:
|
hotfix:
|
||||||
regex: ^hotfix?[\/-](?<BranchName>.+)
|
regex: ^hotfix?[\/-](?<BranchName>.+)
|
||||||
mode: ContinuousDelivery
|
mode: ContinuousDelivery
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ A starting point for new .NET projects, based on opinionated rules.
|
|||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
1. In order to be able to update your repository with the latest changes, you can use the following command **after creating** your repo:
|
1. In order to be able to update your repository with the latest changes, you can use the following command **after creating** your repo:
|
||||||
```bash
|
```bash
|
||||||
git remote add template https://github.com/Cognify-App/templates-dotnet
|
git remote add template https://github.com/kritikos-io/templates-dotnet
|
||||||
git fetch --all
|
git fetch --all
|
||||||
git merge template/main --allow-unrelated-histories
|
git merge template/main --allow-unrelated-histories
|
||||||
```
|
```
|
||||||
1. Do this as soon as possible, as the unrelated histories flag will lead to a few conflicts that you will need to resolve manually.
|
1. Do this as soon as possible, as the unrelated histories flag will lead to a few conflicts that you will need to resolve manually.
|
||||||
1. Afterwards, you can pull future changes using
|
1. Afterwards, you can pull future changes using
|
||||||
```bash
|
```bash
|
||||||
@@ -53,4 +53,4 @@ OpenAPI documents generated at build time are validated using [Spectral]. Config
|
|||||||
|
|
||||||
[Central Package Management]: https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management
|
[Central Package Management]: https://learn.microsoft.com/en-us/nuget/consume-packages/central-package-management
|
||||||
[Entity Framework Core MSBuild integration]: https://learn.microsoft.com/en-us/ef/core/cli/msbuild
|
[Entity Framework Core MSBuild integration]: https://learn.microsoft.com/en-us/ef/core/cli/msbuild
|
||||||
[Spectral]: https://github.com/stoplightio/spectral
|
[Spectral]: https://github.com/stoplightio/spectral
|
||||||
|
|||||||
+5
-28
@@ -4,39 +4,16 @@
|
|||||||
"path": "."
|
"path": "."
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"extensions": {
|
|
||||||
"recommendations": [
|
|
||||||
"EditorConfig.EditorConfig",
|
|
||||||
"mhutchie.git-graph",
|
|
||||||
"ms-dotnettools.csdevkit",
|
|
||||||
"ms-vscode-remote.remote-containers",
|
|
||||||
"seatonjiang.gitmoji-vscode",
|
|
||||||
"redhat.vscode-xml"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"settings": {
|
"settings": {
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
"nuget.config": "xml"
|
"nuget.config": "xml"
|
||||||
},
|
},
|
||||||
"json.schemas": [
|
|
||||||
{
|
|
||||||
"fileMatch": [
|
|
||||||
"xunit.runner.json"
|
|
||||||
],
|
|
||||||
"url": "https://xunit.net/schema/current/xunit.runner.schema.json"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fileMatch": [
|
|
||||||
"stylecop.json"
|
|
||||||
],
|
|
||||||
"url": "https://raw.githubusercontent.com/bjornhellander/NewStyleCopAnalyzers/refs/heads/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"editor.wordWrap": "on",
|
|
||||||
"[xml]": {
|
|
||||||
"editor.defaultFormatter": "redhat.vscode-xml"
|
|
||||||
},
|
|
||||||
"xml.format.maxLineWidth": 0,
|
"xml.format.maxLineWidth": 0,
|
||||||
"xml.format.splitAttributes": "preserve",
|
"xml.format.splitAttributes": "preserve",
|
||||||
|
"github.copilot.chat.commitMessageGeneration.instructions": [
|
||||||
|
{
|
||||||
|
"file": ".github/copilot-commit-message-instructions.md"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<IsPackable>false</IsPackable>
|
<IsPackable>false</IsPackable>
|
||||||
<IsPublishable>false</IsPublishable>
|
<IsPublishable>false</IsPublishable>
|
||||||
<NoWarn>$(NoWarn);SA1600</NoWarn>
|
<NoWarn>$(NoWarn);SA1600;SA1601;CS1591</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<IsPublishable>false</IsPublishable>
|
<IsPublishable>false</IsPublishable>
|
||||||
<IsTestProject>true</IsTestProject>
|
<IsTestProject>true</IsTestProject>
|
||||||
<NoWarn>$(NoWarn);SA1600</NoWarn>
|
<NoWarn>$(NoWarn);SA1600;SA1601;CS1591</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup Label="xUnit Configuration" Condition="Exists('$(MSBuildThisFileDirectory)\..\xunit.runner.json') AND $(IsTestProject)=='True' AND @(PackageReference->StartsWith('xunit')->Count()) > 0">
|
<ItemGroup Label="xUnit Configuration" Condition="Exists('$(MSBuildThisFileDirectory)\..\xunit.runner.json') AND $(IsTestProject)=='True' AND @(PackageReference->StartsWith('xunit')->Count()) > 0">
|
||||||
|
|||||||
Reference in New Issue
Block a user