From 2366f91afe12ed5f72ad586edf87756e3d656368 Mon Sep 17 00:00:00 2001 From: raj pandey Date: Thu, 9 Apr 2026 12:29:18 +0530 Subject: [PATCH 1/4] update: added skill files --- .cursor/rules/README.md | 5 ++ AGENTS.md | 62 ++++++++++++++ skills/README.md | 15 ++++ skills/code-review/SKILL.md | 37 +++++++++ skills/contentstack-utils/SKILL.md | 127 +++++++++++++++++++++++++++++ skills/csharp-style/SKILL.md | 45 ++++++++++ skills/dev-workflow/SKILL.md | 64 +++++++++++++++ skills/testing/SKILL.md | 64 +++++++++++++++ 8 files changed, 419 insertions(+) create mode 100644 .cursor/rules/README.md create mode 100644 AGENTS.md create mode 100644 skills/README.md create mode 100644 skills/code-review/SKILL.md create mode 100644 skills/contentstack-utils/SKILL.md create mode 100644 skills/csharp-style/SKILL.md create mode 100644 skills/dev-workflow/SKILL.md create mode 100644 skills/testing/SKILL.md diff --git a/.cursor/rules/README.md b/.cursor/rules/README.md new file mode 100644 index 0000000..e069005 --- /dev/null +++ b/.cursor/rules/README.md @@ -0,0 +1,5 @@ +# Cursor (optional) + +**Cursor** users: start at **[`AGENTS.md`](../../AGENTS.md)** at the repository root. All conventions live in **`skills/*/SKILL.md`**. + +This folder only points contributors to **`AGENTS.md`** so editor-specific configuration does not duplicate the canonical documentation. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..145c05f --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,62 @@ +# Contentstack Utils .NET – Agent guide + +**Universal entry point** for contributors and AI agents. Detailed conventions live in **`skills/*/SKILL.md`**. + +## What this repo is + +| Field | Detail | +|-------|--------| +| **Name:** | [contentstack-utils-dotnet](https://github.com/contentstack/contentstack-utils-dotnet) | +| **Purpose:** | NuGet library **`contentstack.utils`**: JSON RTE → HTML rendering, embedded entry/asset rendering, GQL-oriented helpers, variant metadata (`GetVariantMetadataTags` / `GetVariantAliases`), Live Preview–style editable tags (`addEditableTags`). This is **not** a full Contentstack Delivery or Management HTTP SDK. | +| **Out of scope (if any):** | No built-in HTTP client to Contentstack APIs; consumers use the Contentstack .NET Delivery SDK or other clients. This package focuses on parsing, rendering, and JSON helpers. | + +## Tech stack (at a glance) + +| Area | Details | +|------|---------| +| **Language** | C#; library multi-targets **netstandard2.0**, **net47**, **net472** ([`Contentstack.Utils/Contentstack.Utils.csproj`](Contentstack.Utils/Contentstack.Utils.csproj)); test project **net7.0** ([`Contentstack.Utils.Tests/Contentstack.Utils.Tests.csproj`](Contentstack.Utils.Tests/Contentstack.Utils.Tests.csproj)). | +| **Build** | **dotnet** + solution [`Contentstack.Utils.sln`](Contentstack.Utils.sln); shared package version in [`Directory.Build.props`](Directory.Build.props) (e.g. `Version` **1.2.0**). | +| **Tests** | **xUnit**, **Microsoft.NET.Test.Sdk**, **coverlet.collector**; JSON fixtures under [`Contentstack.Utils.Tests/Resources/`](Contentstack.Utils.Tests/Resources/). | +| **Lint / coverage** | No repo-level `.editorconfig` or format workflow; tests use **Coverlet** (`XPlat code coverage`) via the shell scripts. | +| **Key dependencies** | **HtmlAgilityPack**, **Newtonsoft.Json** in the library; tests reference compatible Newtonsoft.Json. | + +## Commands (quick reference) + +| Command type | Command | +|--------------|---------| +| **Build** | `dotnet build Contentstack.Utils.sln` (add `-c Release` for release configuration). | +| **Test (quick, local)** | `dotnet test Contentstack.Utils.sln` — from repo root; no TRX/coverage (fastest feedback). | +| **Test (CI parity)** | `sh ./Scripts/run-unit-test-case.sh` — clears `Contentstack.Utils.Tests/TestResults`, runs `dotnet test` on the test project with TRX logging and coverage. | +| **Test + HTML coverage report** | `bash ./Scripts/run-test-case.sh` — tests the **solution**, then runs `python3 Scripts/generate_test_report.py` to emit HTML under `Contentstack.Utils.Tests/TestResults/Coverage-.../index.html`. | +| **Pack (release)** | `dotnet pack -c Release -o out` (see [`.github/workflows/nuget-publish.yml`](.github/workflows/nuget-publish.yml)). | +| **SCA (local parity with CI)** | `dotnet restore ./Contentstack.Utils.sln`, then from `Contentstack.Utils`: `snyk test` (requires Snyk CLI and `SNYK_TOKEN`; see [`sca-scan.yml`](.github/workflows/sca-scan.yml)). | + +**CI:** [`.github/workflows/unit-test.yml`](.github/workflows/unit-test.yml) runs `run-unit-test-case.sh` on Windows for `pull_request` and `push`. + +## CI and automation (workflows) + +| Workflow | Trigger | Role | +|----------|---------|------| +| [`unit-test.yml`](.github/workflows/unit-test.yml) | `pull_request`, `push` | Windows: unit tests via `Scripts/run-unit-test-case.sh`. | +| [`check-branch.yml`](.github/workflows/check-branch.yml) | `pull_request` | Merges into **`master`** are only allowed from **`staging`** (otherwise fails with a PR comment). | +| [`nuget-publish.yml`](.github/workflows/nuget-publish.yml) | `release` (created) | `dotnet pack -c Release -o out`; push package to NuGet.org and GitHub Packages. | +| [`sca-scan.yml`](.github/workflows/sca-scan.yml) | PR (opened, synchronize, reopened) | Ubuntu: `dotnet restore`, **Snyk** `snyk test` under `Contentstack.Utils`. | +| [`policy-scan.yml`](.github/workflows/policy-scan.yml) | PR (public repos) | Requires `SECURITY.md` and a license file containing the current year. | +| [`codeql-analysis.yml`](.github/workflows/codeql-analysis.yml) | `pull_request` (branches `*`) | CodeQL analysis for **csharp** (autobuild). | +| [`issues-jira.yml`](.github/workflows/issues-jira.yml) | `issues` (opened) | Creates Jira tickets from GitHub issues (secrets). | + +## Where the documentation lives: skills + +| Skill | Path | What it covers | +|-------|------|----------------| +| Dev workflow | [`skills/dev-workflow/SKILL.md`](skills/dev-workflow/SKILL.md) | Branches, build/test/pack, CI, security workflows, CODEOWNERS, Talisman. | +| Testing | [`skills/testing/SKILL.md`](skills/testing/SKILL.md) | xUnit layout, fixtures, mocks, coverage scripts, alignment with CI. | +| Code review | [`skills/code-review/SKILL.md`](skills/code-review/SKILL.md) | PR expectations, checklist, security notes. | +| Contentstack Utils (API) | [`skills/contentstack-utils/SKILL.md`](skills/contentstack-utils/SKILL.md) | Public API, package boundaries, `Utils` / GQL / variants, dependencies. | +| C# style (this repo) | [`skills/csharp-style/SKILL.md`](skills/csharp-style/SKILL.md) | Folder layout, namespaces, naming consistency, TFMs. | + +An index with “when to use” hints is in [`skills/README.md`](skills/README.md). + +## Using Cursor (optional) + +If you use **Cursor**, [`.cursor/rules/README.md`](.cursor/rules/README.md) only points to **[`AGENTS.md`](AGENTS.md)** at the repo root. All conventions live in **`skills/*/SKILL.md`**—same docs as for any other tool. diff --git a/skills/README.md b/skills/README.md new file mode 100644 index 0000000..b8c6c0b --- /dev/null +++ b/skills/README.md @@ -0,0 +1,15 @@ +# Skills – Contentstack Utils .NET + +Source of truth for detailed guidance is **`skills/*/SKILL.md`**. Read **[`AGENTS.md`](../AGENTS.md)** first, then open the skill that matches your task. + +## When to use which skill + +| Skill folder | Use when | +|--------------|----------| +| [`dev-workflow`](dev-workflow/SKILL.md) | Branch rules, local build/pack, test scripts, CI workflows, versioning, security scans, CODEOWNERS, Talisman. | +| [`testing`](testing/SKILL.md) | Writing or running xUnit tests, fixtures, mocks, coverage, matching CI behavior. | +| [`code-review`](code-review/SKILL.md) | Preparing or reviewing PRs, release/docs expectations, dependency risk. | +| [`contentstack-utils`](contentstack-utils/SKILL.md) | Public API (`Utils`, GQL helpers, variants, `Options`), NuGet package boundaries, converters, dependencies. | +| [`csharp-style`](csharp-style/SKILL.md) | Where to put new types, namespaces, naming consistency, multi-target framework constraints. | + +Each folder contains **`SKILL.md`** with YAML frontmatter (`name`, `description`). diff --git a/skills/code-review/SKILL.md b/skills/code-review/SKILL.md new file mode 100644 index 0000000..d49da18 --- /dev/null +++ b/skills/code-review/SKILL.md @@ -0,0 +1,37 @@ +--- +name: code-review +description: Use for PR expectations, review checklist, docs/changelog, and security considerations in contentstack-utils-dotnet. +--- + +# Code review – Contentstack Utils .NET + +## When to use + +- Opening or reviewing a pull request. +- Deciding whether README/CHANGELOG updates or extra tests are required. +- Assessing impact of new dependencies or public API changes. + +## Instructions + +### Branch and ownership + +- Merges into **`master`** are expected from **`staging`** only (see [`check-branch.yml`](../../.github/workflows/check-branch.yml)). Align your PR base/head with team process. +- [`CODEOWNERS`](../../CODEOWNERS) may request reviews from **`@contentstack/devex-pr-reviewers`** and security admins for workflow or `.snyk` changes. + +### Checklist + +- **Behavior**: New or changed logic in [`Contentstack.Utils`](../../Contentstack.Utils/) should have **xUnit** coverage in [`Contentstack.Utils.Tests`](../../Contentstack.Utils.Tests/) unless truly non-functional (e.g. comment-only). +- **Public API**: User-visible changes should update [`README.md`](../../README.md) and [`CHANGELOG.md`](../../CHANGELOG.md) as appropriate. +- **Multi-targeting**: The library builds **netstandard2.0**, **net47**, **net472**. After API or dependency changes, verify `dotnet build` succeeds for all target frameworks (or rely on CI). +- **Dependencies**: New or upgraded NuGet packages affect **Snyk** ([`sca-scan.yml`](../../.github/workflows/sca-scan.yml)) and **CodeQL** ([`codeql-analysis.yml`](../../.github/workflows/codeql-analysis.yml)). Ensure licenses and advisories are acceptable. +- **Secrets**: Never commit API keys, tokens, or connection strings. CI uses GitHub secrets only. + +### Severity labels (optional) + +Teams may use **Blocker** (must fix before merge), **Major** (should fix or track), **Minor** (nit / follow-up)—keep comments actionable. + +## References + +- [`skills/dev-workflow/SKILL.md`](../dev-workflow/SKILL.md) — CI and branch rules. +- [`skills/testing/SKILL.md`](../testing/SKILL.md) — how to add tests. +- [`skills/contentstack-utils/SKILL.md`](../contentstack-utils/SKILL.md) — API surface and boundaries. diff --git a/skills/contentstack-utils/SKILL.md b/skills/contentstack-utils/SKILL.md new file mode 100644 index 0000000..e1b0330 --- /dev/null +++ b/skills/contentstack-utils/SKILL.md @@ -0,0 +1,127 @@ +--- +name: contentstack-utils +description: Use for the contentstack.utils NuGet API—Utils, GQL, Options, variants, converters, code flows, and integration boundaries. +--- + +# Contentstack Utils (API) – Contentstack Utils .NET + +## When to use + +- Implementing or extending JSON RTE → HTML rendering or embedded content behavior. +- Adding node types, converters, or variant/metadata helpers. +- Choosing whether logic belongs in this package vs the Contentstack .NET Delivery SDK. + +## Instructions + +### Package and namespaces + +- **NuGet package id:** `contentstack.utils` ([`Contentstack.Utils.csproj`](../../Contentstack.Utils/Contentstack.Utils.csproj)). +- **Root namespace:** `Contentstack.Utils`. Sub-namespaces follow folders: **`Contentstack.Utils.Models`**, **`Contentstack.Utils.Interfaces`**, **`Contentstack.Utils.Enums`**, **`Contentstack.Utils.Extensions`**, **`Contentstack.Utils.Converters`**. + +### Models (library) + +Source files under [`Contentstack.Utils/Models/`](../../Contentstack.Utils/Models/): + +- [`JsonRTENode.cs`](../../Contentstack.Utils/Models/JsonRTENode.cs), [`JsonRTENodes.cs`](../../Contentstack.Utils/Models/JsonRTENodes.cs) — GQL-shaped RTE wrappers. +- [`Metadata.cs`](../../Contentstack.Utils/Models/Metadata.cs) — embed metadata; implicit conversions from **HtmlAgilityPack** `HtmlNode` and RTE `Node`. +- [`Node.cs`](../../Contentstack.Utils/Models/Node.cs), [`TextNode.cs`](../../Contentstack.Utils/Models/TextNode.cs) — RTE tree nodes. +- [`Options.cs`](../../Contentstack.Utils/Models/Options.cs) — default rendering; subclass for custom HTML. + +### Interfaces (embedding and rendering) + +- **`IEntryEmbedable`** — [`IEntryEmbedable.cs`](../../Contentstack.Utils/Interfaces/IEntryEmbedable.cs): `embeddedItems` map for resolving references. +- **`IEmbeddedObject`**, **`IEmbeddedEntry`**, **`EditableEntry`**, **`IEmbeddedAsset`** — [`IEmbeddedObject.cs`](../../Contentstack.Utils/Interfaces/IEmbeddedObject.cs). +- **`IRenderable`**, **`NodeChildrenCallBack`** — [`IOptions.cs`](../../Contentstack.Utils/Interfaces/IOptions.cs). +- **`IEdges`** — [`IEdges.cs`](../../Contentstack.Utils/Interfaces/IEdges.cs) (GQL edge list). Spelling **`IEntryEmbedable`** matches the existing public API. + +### Core type: `Contentstack.Utils.Utils` + +[`Utils.cs`](../../Contentstack.Utils/Utils.cs) exposes static helpers including: + +- **`JsonToHtml`**: Overloads for `Node`, `List` — see [Code flows](#code-flows). +- **`RenderContent`**: Overloads for `string` and `List` HTML — see [Code flows](#code-flows). +- **`Utils.GQL`**: `JsonToHtml` for `JsonRTENode` / `JsonRTENodes` where `T : IEmbeddedObject` — see [Code flows](#code-flows). +- **`addEditableTags`**: Adds Live Preview–style **`data-cslp`** (or object-shaped) metadata on **`EditableEntry`** graphs for a given content type and locale (see [`Utils.addEditableTags`](../../Contentstack.Utils/Utils.cs)). +- **Variants / metadata:** + - **`GetVariantAliases`** — reads each entry’s `publish_details` → `variants` object and collects non-empty **`alias`** values per variant entry (implementation: **`ExtractVariantAliasesFromEntry`** in [`Utils.cs`](../../Contentstack.Utils/Utils.cs), approx. lines 401–426). + - **`GetVariantMetadataTags`** — wraps alias data into a **`JObject`** with key **`data-csvariants`** (compact JSON string). + - **`GetDataCsvariantsAttribute`** — **Obsolete**; use **`GetVariantMetadataTags`** instead (same behavior; see XML comments on [`Utils`](../../Contentstack.Utils/Utils.cs)). + +### Rendering hooks (`Options` / `IRenderable`) + +Subclass or configure **[`Options.cs`](../../Contentstack.Utils/Models/Options.cs)** (`Options : IRenderable`) to override: + +- **`RenderOption(IEmbeddedObject, Metadata)`** +- **`RenderNode(string nodeType, Node, NodeChildrenCallBack)`** +- **`RenderMark(MarkType, string text, string className, string Id)`** + +### JSON serialization + +- [`NodeJsonConverter.cs`](../../Contentstack.Utils/Converters/NodeJsonConverter.cs) and [`RTEJsonConverter.cs`](../../Contentstack.Utils/Converters/RTEJsonConverter.cs) integrate with **Newtonsoft.Json** for RTE node graphs. New node shapes should follow the same converter and model patterns. + +### Dependencies + +- **HtmlAgilityPack**: HTML load, query, and embedded-object replacement for `RenderContent`. +- **Newtonsoft.Json**: JSON models (`JObject`, `JArray`, converters). Upgrades should stay compatible with consumers and pass Snyk/CI. + +### Out of scope + +- This library **does not** ship an HTTP client for Contentstack Delivery or Management APIs. Apps typically use **Contentstack .NET SDK** (or REST) to fetch entries, then use **Utils** to render RTE HTML or process JSON. Keep HTTP, auth, and caching in application or SDK layers. + +### Authoritative source + +- **Signatures and full behavior** live in C# under [`Contentstack.Utils/`](../../Contentstack.Utils/). This skill summarizes; when in doubt, read the implementation (especially [`Utils.cs`](../../Contentstack.Utils/Utils.cs)). + +## Code flows + +Stepwise behavior with pointers into [`Utils.cs`](../../Contentstack.Utils/Utils.cs). Line numbers are approximate; verify against the file after large edits. + +### RTE JSON → HTML (`JsonToHtml`) + +1. **`JsonToHtml(Node, Options)`** (approx. lines 97–113) builds a **`referenceToHtml`** delegate: for **`reference`** nodes it calls **`findEmbeddedObject`** using **`options.entry.embeddedItems`**, then **`options.RenderOption`** when a match exists. +2. **`nodeChildrenToHtml`** (lines 115–118) concatenates HTML for each child via **`nodeToHtml`**. +3. **`nodeToHtml`** (lines 121–131): **`type == "text"`** → **`textToHtml`** (lines 133+), which applies marks in order via **`RenderMark`**; **`type == "reference"`** → **`referenceToHtml`**; **otherwise** → **`options.RenderNode`** with a callback that recurses into **`nodeChildrenToHtml`**. + +### GQL RTE (`Utils.GQL.JsonToHtml`) + +- Reuses **`nodeChildrenToHtml`** / **`nodeToHtml`**. **`referenceToHtml`** is built by **`GQL.refernceToHtml`** (lines 32–50): find **`IEdges`** where **`edge.Node`** matches **`Metadata.ItemUid`** and **`ContentTypeUid`**, then **`options.RenderOption(edge.Node, metadata)`**. Entry points: **`GQL.JsonToHtml(JsonRTENode, ...)`** (lines 17–20) and list overload (lines 22–30). + +### HTML string with embeds (`RenderContent`) + +1. **`RenderContent(string, Options)`** (lines 64–82): **`HtmlDocument.LoadHtml`**, then **`FindEmbeddedObject`** extension on [`HtmlDocumentExtension.cs`](../../Contentstack.Utils/Extensions/HtmlDocumentExtension.cs) (selects nodes with class **`embedded-asset`** or **`embedded-entry`**). +2. Each **HtmlNode** is passed to the callback; **`Metadata`** is produced via **implicit conversion** from **`HtmlNode`** ([`Metadata.cs`](../../Contentstack.Utils/Models/Metadata.cs), lines 46–68). +3. **`findEmbeddedObject`** resolves **`IEmbeddedObject`** from **`options.entry.embeddedItems`**; result string replaces **`metadata.OuterHTML`** in the accumulated HTML. + +### Variant metadata (`GetVariantAliases` / `GetVariantMetadataTags`) + +- **`ExtractVariantAliasesFromEntry`**: requires **`entry["publish_details"]`** as **`JObject`**, then **`publish_details["variants"]`** as **`JObject`**; for each property, reads **`alias`** from the nested object when present (lines 401–426). +- **`GetVariantMetadataTags`** builds **`{ "data-csvariants": }`** from **`GetVariantAliases`** results (lines 365–380). + +### Diagrams (high level) + +```mermaid +flowchart TD + rteEntry[JsonToHtml_Node_or_List] + rteEntry --> nodeChildren[nodeChildrenToHtml] + nodeChildren --> nodeTo[nodeToHtml] + nodeTo -->|text| textTo[textToHtml_RenderMark_chain] + nodeTo -->|reference| refDel[referenceToHtml_findEmbeddedObject_RenderOption] + nodeTo -->|other_types| renderNode[RenderNode_recursive_callback] +``` + +```mermaid +flowchart TD + htmlEntry[RenderContent_string] + htmlEntry --> load[HtmlDocument_LoadHtml] + load --> find[FindEmbeddedObject_extension] + find --> meta[HtmlNode_to_Metadata_implicit] + meta --> resolve[findEmbeddedObject_embeddedItems] + resolve --> replace[Replace_OuterHTML_with_RenderOption] +``` + +## References + +- [`skills/csharp-style/SKILL.md`](../csharp-style/SKILL.md) — layout and naming in this repo. +- [`skills/testing/SKILL.md`](../testing/SKILL.md) — how to test API changes. +- [Product README](../../README.md) — install and usage examples. +- [Contentstack .NET Utils on NuGet](https://www.nuget.org/packages/contentstack.utils) — package listing (verify version). diff --git a/skills/csharp-style/SKILL.md b/skills/csharp-style/SKILL.md new file mode 100644 index 0000000..95fb81a --- /dev/null +++ b/skills/csharp-style/SKILL.md @@ -0,0 +1,45 @@ +--- +name: csharp-style +description: Use for folder placement, namespaces, naming consistency, and multi-target framework rules in Contentstack.Utils. +--- + +# C# style (this repo) – Contentstack Utils .NET + +## When to use + +- Adding new types to the library or tests. +- Choosing namespaces and file locations to match existing structure. +- Ensuring changes remain compatible with **netstandard2.0** and desktop TFMs. + +## Instructions + +### Library folder taxonomy + +Under [`Contentstack.Utils/`](../../Contentstack.Utils/), place new code according to its role: + +| Folder | Contents | +|--------|----------| +| `Interfaces/` | [`IEntryEmbedable.cs`](../../Contentstack.Utils/Interfaces/IEntryEmbedable.cs) (`IEntryEmbedable`); [`IEmbeddedObject.cs`](../../Contentstack.Utils/Interfaces/IEmbeddedObject.cs) (`IEmbeddedObject`, `IEmbeddedEntry`, `EditableEntry`, `IEmbeddedAsset`); [`IOptions.cs`](../../Contentstack.Utils/Interfaces/IOptions.cs) (`IRenderable`, `NodeChildrenCallBack`); [`IEdges.cs`](../../Contentstack.Utils/Interfaces/IEdges.cs) (`IEdges`). | +| `Models/` | DTOs and [`Options.cs`](../../Contentstack.Utils/Models/Options.cs) (`Options` base class). | +| `Enums/` | [`MarkType`](../../Contentstack.Utils/Enums/MarkType.cs), [`StyleType`](../../Contentstack.Utils/Enums/StyleType.cs), [`EmbedItemType`](../../Contentstack.Utils/Enums/EmbedItemType.cs). | +| `Extensions/` | Extension methods — [`HtmlDocumentExtension.cs`](../../Contentstack.Utils/Extensions/HtmlDocumentExtension.cs) (`FindEmbeddedObject` on **HtmlAgilityPack** `HtmlDocument`). | +| `Converters/` | Newtonsoft.Json converters for RTE/node JSON ([`NodeJsonConverter.cs`](../../Contentstack.Utils/Converters/NodeJsonConverter.cs), [`RTEJsonConverter.cs`](../../Contentstack.Utils/Converters/RTEJsonConverter.cs)). | +| `Constants/` | Shared strings — [`ErrorMessages.cs`](../../Contentstack.Utils/Constants/ErrorMessages.cs). | + +### Namespaces + +- Mirror the folder structure: `Contentstack.Utils.Interfaces`, `Contentstack.Utils.Models`, and so on. Keep **`Contentstack.Utils`** as the root for public surface consistency. + +### Naming consistency + +- The codebase mixes typical .NET **PascalCase** for most public members with some **camelCase** public static names (notably **`addEditableTags`** on [`Utils`](../../Contentstack.Utils/Utils.cs)). For new code, **prefer consistency with the nearest existing API** in the same class or feature area rather than blindly applying IDE defaults, so consumers see uniform style per subsystem. + +### Target frameworks + +- **Library** ([`Contentstack.Utils.csproj`](../../Contentstack.Utils/Contentstack.Utils.csproj)): **netstandard2.0**, **net47**, **net472**. Public APIs must be implementable on all targets; avoid APIs that only compile on .NET 5+ unless you intentionally raise baselines with a major version policy. +- **Tests** ([`Contentstack.Utils.Tests.csproj`](../../Contentstack.Utils.Tests/Contentstack.Utils.Tests.csproj)): **net7.0** only—fine for test-only APIs; do not assume test-only APIs exist in the library. + +## References + +- [`skills/contentstack-utils/SKILL.md`](../contentstack-utils/SKILL.md) — what belongs in the public API. +- [`skills/testing/SKILL.md`](../testing/SKILL.md) — test project structure. diff --git a/skills/dev-workflow/SKILL.md b/skills/dev-workflow/SKILL.md new file mode 100644 index 0000000..d9db3b7 --- /dev/null +++ b/skills/dev-workflow/SKILL.md @@ -0,0 +1,64 @@ +--- +name: dev-workflow +description: Use for branches, build/pack, test scripts, CI workflows, versioning, CODEOWNERS, and security tooling in contentstack-utils-dotnet. +--- + +# Dev workflow – Contentstack Utils .NET + +## When to use + +- Setting up the repo locally, cutting releases, or debugging CI. +- Changing GitHub Actions, branch protection expectations, or dependency scanning. +- Bumping package version or understanding how NuGet publish is triggered. + +## Instructions + +### Branching and merges + +- [`.github/workflows/check-branch.yml`](../../.github/workflows/check-branch.yml) runs on **pull requests**. If the base branch is **`master`** and the head branch is **not** **`staging`**, the job fails and [thollander/actions-comment-pull-request](https://github.com/thollander/actions-comment-pull-request) posts an explanatory comment. To merge into `master`, open a PR **from `staging`** (per current org policy). + +### Versioning + +- Package version is centralized in [`Directory.Build.props`](../../Directory.Build.props) (`Version` property). [`Contentstack.Utils.csproj`](../../Contentstack.Utils/Contentstack.Utils.csproj) uses `PackageVersion` / `ReleaseVersion` tied to `$(Version)` where applicable—bump version in one place for releases. + +### Build + +- From repo root: `dotnet build Contentstack.Utils.sln` (use `-c Release` for release builds). + +### Test scripts + +- **`Scripts/run-unit-test-case.sh`**: Deletes `Contentstack.Utils.Tests/TestResults`, runs `dotnet test Contentstack.Utils.Tests/Contentstack.Utils.Tests.csproj` with TRX logger `Report-Contentstack-DotNet-Test-Case.trx` and `XPlat code coverage`. This is what [`.github/workflows/unit-test.yml`](../../.github/workflows/unit-test.yml) runs on **Windows**. +- **`Scripts/run-test-case.sh`**: Runs `dotnet test` on the **solution** with a date-stamped TRX name, collects coverage, finds `coverage.cobertura.xml`, then runs **`python3 Scripts/generate_test_report.py`** to produce HTML under `Contentstack.Utils.Tests/TestResults/Coverage-.../index.html`. Use this for a local combined test + coverage report (Python 3 stdlib only). + +### Pack and publish + +- Local pack: `dotnet pack -c Release -o out` (same as [`.github/workflows/nuget-publish.yml`](../../.github/workflows/nuget-publish.yml)). +- Publishing: triggered on **GitHub release created**. Jobs build on Windows, pack, and push `contentstack.utils.*.nupkg` to NuGet.org and GitHub Packages (requires GitHub secrets, including **`NUGET_API_KEY`** for NuGet.org and GitHub Packages auth where applicable; do not commit secrets). + +### CI and security jobs + +| Workflow | Purpose | +|----------|---------| +| `unit-test.yml` | Windows unit tests via `run-unit-test-case.sh`. | +| `check-branch.yml` | Enforce `staging` → `master` for PRs. | +| `nuget-publish.yml` | Pack and push on release. | +| `sca-scan.yml` | `dotnet restore` + **Snyk** `snyk test` in `Contentstack.Utils` (needs `SNYK_TOKEN`). | +| `policy-scan.yml` | For **public** repos: `SECURITY.md` and license file with current calendar year. | +| `codeql-analysis.yml` | CodeQL **csharp** with autobuild. | +| `issues-jira.yml` | Mirror new issues to Jira (Atlassian actions + secrets). | + +### CODEOWNERS + +- [`CODEOWNERS`](../../CODEOWNERS): default review **`@contentstack/devex-pr-reviewers`**; **`@contentstack/security-admin`** for security workflows, `.snyk`, and related paths. +- **Note:** `CODEOWNERS` references `.github/workflows/codeql-anaylsis.yml` (typo). The actual file is **`codeql-analysis.yml`**. Fix the typo in `CODEOWNERS` in a dedicated PR if you want CodeQL ownership to apply. + +### Talisman + +- [`.talismanrc`](../../.talismanrc) pins checksums for specific files. Do not add ignores or weaken checks without security team agreement. + +## References + +- [`skills/testing/SKILL.md`](../testing/SKILL.md) — test project and coverage. +- [`skills/contentstack-utils/SKILL.md`](../contentstack-utils/SKILL.md) — library API and boundaries. +- [`skills/code-review/SKILL.md`](../code-review/SKILL.md) — PR checklist. +- [GitHub Actions documentation](https://docs.github.com/actions) — workflow syntax and secrets. diff --git a/skills/testing/SKILL.md b/skills/testing/SKILL.md new file mode 100644 index 0000000..faeb013 --- /dev/null +++ b/skills/testing/SKILL.md @@ -0,0 +1,64 @@ +--- +name: testing +description: Use for xUnit tests, JSON fixtures, mocks, Coverlet coverage, and scripts in Contentstack.Utils.Tests. +--- + +# Testing – Contentstack Utils .NET + +## When to use + +- Adding or changing behavior in `Contentstack.Utils` and needing unit tests. +- Debugging CI test failures on Windows (unit-test workflow). +- Generating local HTML coverage reports. + +## Instructions + +### Test project + +- [`Contentstack.Utils.Tests.csproj`](../../Contentstack.Utils.Tests/Contentstack.Utils.Tests.csproj): targets **net7.0**, **IsPackable** false, references the main library project. +- Packages: **xunit**, **xunit.runner.visualstudio**, **Microsoft.NET.Test.Sdk**, **coverlet.collector**, **Newtonsoft.Json** (aligned with test needs). + +### Test classes (inventory) + +Use these as a map of coverage areas when adding related behavior: + +| Class | Focus | +|-------|--------| +| `JsonToHtmlTest` | JSON RTE → HTML | +| `GQLTest` | `Utils.GQL` / GraphQL-shaped RTE | +| `UtilsTest` | Core `Utils` APIs | +| `UtilsArrayStringTest` | Array/string rendering paths | +| `UtilsCustomRenderTest` | Custom `Options` / rendering | +| `DefaultRenderTest` | Default render behavior | +| `HtmlDocumentExtensionTest` | HTML document extensions | +| `MetadataTest` | Embedded metadata | +| `VariantAliasesTest` | Variant aliases / metadata tags | + +### Fixtures and content + +- JSON files live under [`Contentstack.Utils.Tests/Resources/`](../../Contentstack.Utils.Tests/Resources/). The csproj uses `Content Include="Resources\**\*.json" CopyToOutputDirectory="PreserveNewest"` so files are available at test runtime. +- Checked-in fixtures: [`variantsSingleEntry.json`](../../Contentstack.Utils.Tests/Resources/variantsSingleEntry.json), [`variantsEntries.json`](../../Contentstack.Utils.Tests/Resources/variantsEntries.json). + +### Constants, helpers, mocks + +- Shared expected strings/constants: [`Constants/`](../../Contentstack.Utils.Tests/Constants/). +- Parsing helpers: [`Helpers/NodeParser.cs`](../../Contentstack.Utils.Tests/Helpers/NodeParser.cs). +- Test doubles in [`Mocks/`](../../Contentstack.Utils.Tests/Mocks/): [`CustomRenderOptionMock.cs`](../../Contentstack.Utils.Tests/Mocks/CustomRenderOptionMock.cs), [`DefaultRenderMock.cs`](../../Contentstack.Utils.Tests/Mocks/DefaultRenderMock.cs), [`EmbeddedModelMock.cs`](../../Contentstack.Utils.Tests/Mocks/EmbeddedModelMock.cs), [`GQLModel.cs`](../../Contentstack.Utils.Tests/Mocks/GQLModel.cs). Follow existing patterns for new scenarios. + +### Quick local test + +- From repo root: `dotnet test Contentstack.Utils.sln` — runs all tests without the shell scripts (no TRX or coverage collection). + +### Coverage + +- Scripts use Coverlet’s **XPlat code coverage** and emit Cobertura XML (e.g. `coverage.cobertura.xml` under `TestResults`). +- For HTML: run [`Scripts/run-test-case.sh`](../../Scripts/run-test-case.sh), which invokes [`Scripts/generate_test_report.py`](../../Scripts/generate_test_report.py) (Python 3, standard library only). + +### CI alignment + +- GitHub Actions runs [`Scripts/run-unit-test-case.sh`](../../Scripts/run-unit-test-case.sh) on **Windows**. When reproducing CI failures, use that script (or the same `dotnet test` arguments) from repo root. + +## References + +- [`skills/dev-workflow/SKILL.md`](../dev-workflow/SKILL.md) — scripts and workflows. +- [`skills/contentstack-utils/SKILL.md`](../contentstack-utils/SKILL.md) — APIs under test. From 9771c8c4664e747b8ed3c6a93dd7e1d1eaaadcd8 Mon Sep 17 00:00:00 2001 From: raj pandey Date: Sat, 11 Apr 2026 13:44:12 +0530 Subject: [PATCH 2/4] Removed the references --- skills/code-review/SKILL.md | 6 ------ skills/contentstack-utils/SKILL.md | 2 -- skills/csharp-style/SKILL.md | 5 ----- skills/dev-workflow/SKILL.md | 3 --- skills/testing/SKILL.md | 5 ----- 5 files changed, 21 deletions(-) diff --git a/skills/code-review/SKILL.md b/skills/code-review/SKILL.md index d49da18..1002ee7 100644 --- a/skills/code-review/SKILL.md +++ b/skills/code-review/SKILL.md @@ -29,9 +29,3 @@ description: Use for PR expectations, review checklist, docs/changelog, and secu ### Severity labels (optional) Teams may use **Blocker** (must fix before merge), **Major** (should fix or track), **Minor** (nit / follow-up)—keep comments actionable. - -## References - -- [`skills/dev-workflow/SKILL.md`](../dev-workflow/SKILL.md) — CI and branch rules. -- [`skills/testing/SKILL.md`](../testing/SKILL.md) — how to add tests. -- [`skills/contentstack-utils/SKILL.md`](../contentstack-utils/SKILL.md) — API surface and boundaries. diff --git a/skills/contentstack-utils/SKILL.md b/skills/contentstack-utils/SKILL.md index e1b0330..ff548d9 100644 --- a/skills/contentstack-utils/SKILL.md +++ b/skills/contentstack-utils/SKILL.md @@ -121,7 +121,5 @@ flowchart TD ## References -- [`skills/csharp-style/SKILL.md`](../csharp-style/SKILL.md) — layout and naming in this repo. -- [`skills/testing/SKILL.md`](../testing/SKILL.md) — how to test API changes. - [Product README](../../README.md) — install and usage examples. - [Contentstack .NET Utils on NuGet](https://www.nuget.org/packages/contentstack.utils) — package listing (verify version). diff --git a/skills/csharp-style/SKILL.md b/skills/csharp-style/SKILL.md index 95fb81a..338e01b 100644 --- a/skills/csharp-style/SKILL.md +++ b/skills/csharp-style/SKILL.md @@ -38,8 +38,3 @@ Under [`Contentstack.Utils/`](../../Contentstack.Utils/), place new code accordi - **Library** ([`Contentstack.Utils.csproj`](../../Contentstack.Utils/Contentstack.Utils.csproj)): **netstandard2.0**, **net47**, **net472**. Public APIs must be implementable on all targets; avoid APIs that only compile on .NET 5+ unless you intentionally raise baselines with a major version policy. - **Tests** ([`Contentstack.Utils.Tests.csproj`](../../Contentstack.Utils.Tests/Contentstack.Utils.Tests.csproj)): **net7.0** only—fine for test-only APIs; do not assume test-only APIs exist in the library. - -## References - -- [`skills/contentstack-utils/SKILL.md`](../contentstack-utils/SKILL.md) — what belongs in the public API. -- [`skills/testing/SKILL.md`](../testing/SKILL.md) — test project structure. diff --git a/skills/dev-workflow/SKILL.md b/skills/dev-workflow/SKILL.md index d9db3b7..1e7340e 100644 --- a/skills/dev-workflow/SKILL.md +++ b/skills/dev-workflow/SKILL.md @@ -58,7 +58,4 @@ description: Use for branches, build/pack, test scripts, CI workflows, versionin ## References -- [`skills/testing/SKILL.md`](../testing/SKILL.md) — test project and coverage. -- [`skills/contentstack-utils/SKILL.md`](../contentstack-utils/SKILL.md) — library API and boundaries. -- [`skills/code-review/SKILL.md`](../code-review/SKILL.md) — PR checklist. - [GitHub Actions documentation](https://docs.github.com/actions) — workflow syntax and secrets. diff --git a/skills/testing/SKILL.md b/skills/testing/SKILL.md index faeb013..e0230d9 100644 --- a/skills/testing/SKILL.md +++ b/skills/testing/SKILL.md @@ -57,8 +57,3 @@ Use these as a map of coverage areas when adding related behavior: ### CI alignment - GitHub Actions runs [`Scripts/run-unit-test-case.sh`](../../Scripts/run-unit-test-case.sh) on **Windows**. When reproducing CI failures, use that script (or the same `dotnet test` arguments) from repo root. - -## References - -- [`skills/dev-workflow/SKILL.md`](../dev-workflow/SKILL.md) — scripts and workflows. -- [`skills/contentstack-utils/SKILL.md`](../contentstack-utils/SKILL.md) — APIs under test. From 70569d3eb85d0d79e9b4180ad10bdf80f690160c Mon Sep 17 00:00:00 2001 From: raj pandey Date: Sat, 11 Apr 2026 13:49:32 +0530 Subject: [PATCH 3/4] Removed redundant skill index in readme --- AGENTS.md | 2 -- skills/README.md | 10 ---------- 2 files changed, 12 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 145c05f..04aebf4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -55,8 +55,6 @@ | Contentstack Utils (API) | [`skills/contentstack-utils/SKILL.md`](skills/contentstack-utils/SKILL.md) | Public API, package boundaries, `Utils` / GQL / variants, dependencies. | | C# style (this repo) | [`skills/csharp-style/SKILL.md`](skills/csharp-style/SKILL.md) | Folder layout, namespaces, naming consistency, TFMs. | -An index with “when to use” hints is in [`skills/README.md`](skills/README.md). - ## Using Cursor (optional) If you use **Cursor**, [`.cursor/rules/README.md`](.cursor/rules/README.md) only points to **[`AGENTS.md`](AGENTS.md)** at the repo root. All conventions live in **`skills/*/SKILL.md`**—same docs as for any other tool. diff --git a/skills/README.md b/skills/README.md index b8c6c0b..79e9d8f 100644 --- a/skills/README.md +++ b/skills/README.md @@ -2,14 +2,4 @@ Source of truth for detailed guidance is **`skills/*/SKILL.md`**. Read **[`AGENTS.md`](../AGENTS.md)** first, then open the skill that matches your task. -## When to use which skill - -| Skill folder | Use when | -|--------------|----------| -| [`dev-workflow`](dev-workflow/SKILL.md) | Branch rules, local build/pack, test scripts, CI workflows, versioning, security scans, CODEOWNERS, Talisman. | -| [`testing`](testing/SKILL.md) | Writing or running xUnit tests, fixtures, mocks, coverage, matching CI behavior. | -| [`code-review`](code-review/SKILL.md) | Preparing or reviewing PRs, release/docs expectations, dependency risk. | -| [`contentstack-utils`](contentstack-utils/SKILL.md) | Public API (`Utils`, GQL helpers, variants, `Options`), NuGet package boundaries, converters, dependencies. | -| [`csharp-style`](csharp-style/SKILL.md) | Where to put new types, namespaces, naming consistency, multi-target framework constraints. | - Each folder contains **`SKILL.md`** with YAML frontmatter (`name`, `description`). From 31753b1879da5b120fac0560ab6e123eed111eee Mon Sep 17 00:00:00 2001 From: raj pandey Date: Sat, 11 Apr 2026 14:12:53 +0530 Subject: [PATCH 4/4] Removed cursor rules from agents.md --- AGENTS.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 04aebf4..c1a49d7 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -54,7 +54,3 @@ | Code review | [`skills/code-review/SKILL.md`](skills/code-review/SKILL.md) | PR expectations, checklist, security notes. | | Contentstack Utils (API) | [`skills/contentstack-utils/SKILL.md`](skills/contentstack-utils/SKILL.md) | Public API, package boundaries, `Utils` / GQL / variants, dependencies. | | C# style (this repo) | [`skills/csharp-style/SKILL.md`](skills/csharp-style/SKILL.md) | Folder layout, namespaces, naming consistency, TFMs. | - -## Using Cursor (optional) - -If you use **Cursor**, [`.cursor/rules/README.md`](.cursor/rules/README.md) only points to **[`AGENTS.md`](AGENTS.md)** at the repo root. All conventions live in **`skills/*/SKILL.md`**—same docs as for any other tool.