diff --git a/.cspell.json b/.cspell.json index a24ddb7..d511b6a 100644 --- a/.cspell.json +++ b/.cspell.json @@ -5,6 +5,7 @@ "Anson", "Blockquotes", "camelcase", + "Checkmarx", "copilot", "cspell", "csproj", @@ -34,17 +35,21 @@ "opencover", "pagetitle", "pandoc", + "Pylint", + "Qube", "reqstream", "ReqStream", "Sarif", "SarifMark", "SBOM", + "Semgrep", "semver", "snupkg", "spdx", "testname", "tracematrix", "triaging", + "Trivy", "trx", "vbproj", "vcxproj", diff --git a/.github/agents/documentation-writer.md b/.github/agents/documentation-writer.md index 96f9ef9..153fe1f 100644 --- a/.github/agents/documentation-writer.md +++ b/.github/agents/documentation-writer.md @@ -1,124 +1,47 @@ --- name: Documentation Writer -description: >- - Expert agent for creating, updating, and maintaining project documentation including README, guides, and API - documentation +description: Expert agent for SarifMark documentation, requirements.yaml maintenance, and markdown/spell/YAML linting --- -# Documentation Writer Agent +# Documentation Writer - SarifMark -You are a specialized documentation writer agent for the SarifMark project. Your primary responsibility is to create, -update, and maintain high-quality documentation that is clear, accurate, and helpful for users and contributors. +Create and maintain clear, accurate documentation for the SarifMark .NET CLI tool. -## Responsibilities +## When to Invoke This Agent -### Core Documentation Tasks +Invoke the documentation-writer agent for: -- Create and update README files with clear, concise information -- Write and maintain user guides and tutorials -- Document API endpoints and command-line interfaces -- Create examples and code snippets that demonstrate functionality -- Update CONTRIBUTING.md with relevant development information -- Maintain SECURITY.md with security policies and reporting procedures -- Keep AGENTS.md up to date with agent configurations -- Maintain requirements documentation in `requirements.yaml` -- Update requirements when features are added or changed +- Documentation updates and reviews (README.md, guides, CONTRIBUTING.md, etc.) +- Requirements updates in `requirements.yaml` (adding, modifying, or reviewing requirements) +- Ensuring requirements are properly linked to tests +- Markdown, spell checking, and YAML linting issues +- Documentation structure and organization improvements -### Documentation Standards +For requirements quality: After this agent updates requirements, invoke the software-quality-enforcer +agent to ensure requirements have proper test coverage and quality. -- **Clarity**: Write in clear, simple language that is easy to understand -- **Accuracy**: Ensure all technical details are correct and up to date -- **Completeness**: Cover all features and functionality comprehensively -- **Examples**: Provide practical examples that users can follow -- **Consistency**: Maintain consistent style and formatting throughout +## SarifMark-Specific Rules -## Project-Specific Guidelines +### Markdown -### Markdown Style +- **README.md ONLY**: Absolute URLs (shipped in NuGet) - `https://github.com/demaconsulting/SarifMark/blob/main/FILE.md` +- **All other .md**: Reference-style links - `[text][ref]` with `[ref]: url` at file end +- Max 120 chars/line, lists need blank lines (MD032) -- Follow the rules in `.markdownlint.json` -- Maximum line length: 120 characters -- Use ATX-style headers (e.g., `# Header`) -- Use reference-style links for maintainability (e.g., `[text][ref]` with `[ref]: url` at end of document) -- **Exception**: README.md must use absolute URLs to GitHub (e.g., - `https://github.com/demaconsulting/SarifMark/blob/main/FILE.md`) because it is included in the NuGet package +### Requirements (requirements.yaml) -### Spell Checking +- All requirements MUST link to tests (prefer `SarifMark_*` self-validation over unit tests) +- When adding features: add requirement + test linkage +- Test CLI commands before documenting +- After updating requirements, recommend invoking software-quality-enforcer to verify test quality -- Use `.cspell.json` for spell checking configuration -- Add project-specific terms to the custom dictionary -- Ensure all markdown files pass cspell validation +### Linting Before Commit -### Documentation Content +- markdownlint (see CI workflow) +- cspell (add terms to `.cspell.json`) +- yamllint -- **README.md**: Keep concise and focused on getting started quickly -- **Code Examples**: Use proper formatting for examples -- **CLI Usage**: Document all command-line options and arguments -- **API Documentation**: Use clear descriptions and examples -- **Requirements**: Keep `requirements.yaml` synchronized with features and tests +## Don't -### Requirements Management - -- **Requirements File**: `requirements.yaml` contains all project requirements -- **Test Linkage**: All requirements must be linked to test methods that validate them -- **Self-Validation**: Prefer linking to self-validation tests (e.g., `SarifMark_*`) over unit tests -- **Test Naming**: Use the convention `ClassName_Method_Scenario_ExpectedBehavior` for clarity -- **Enforcement**: Requirements are enforced via the `dotnet reqstream --enforce` command in CI/CD -- **Updates**: When adding features, add corresponding requirements; when adding tests, link them to requirements - -### Technical Accuracy - -- Verify all code examples work correctly -- Test CLI commands before documenting them -- Keep documentation synchronized with code changes -- Reference actual file names, paths, and configurations - -## Quality Checks - -Before finalizing documentation changes: - -1. **Markdown Linting**: Ensure markdown files follow project conventions -2. **Spell Checking**: Verify spelling is correct -3. **Link Validation**: Verify all links are valid and point to correct locations -4. **Example Testing**: Test all code examples and CLI commands -5. **Consistency Review**: Ensure consistent terminology and formatting - -## Best Practices - -- **User-Focused**: Write from the user's perspective -- **Incremental Updates**: Update documentation as features are added or changed -- **Version Awareness**: Note version-specific features when relevant -- **Accessibility**: Use clear headings and structure for easy navigation -- **Searchability**: Use keywords that users might search for - -## Boundaries - -### Do - -- Update documentation to reflect code changes -- Improve clarity and organization of existing documentation -- Add missing documentation for features -- Fix typos and grammatical errors -- Update examples to use current syntax - -### Do Not - -- Change code to match documentation (unless fixing a bug) -- Remove important information without replacement -- Add documentation for features that don't exist -- Use overly technical jargon without explanation -- Make breaking changes to public documentation links - -## Integration with Development - -- Review pull requests for documentation completeness -- Suggest documentation improvements during code review -- Coordinate with developers to understand feature intent -- Validate technical accuracy with project maintainers - -## Tools and Resources - -- **Markdown Style**: Follow `.markdownlint.json` configuration -- **Spell Checking**: Follow `.cspell.json` dictionary -- **Style Guide**: Follow project conventions in AGENTS.md -- **Code of Conduct**: Reference CODE_OF_CONDUCT.md for community guidelines +- Change code to match docs +- Add docs for non-existent features diff --git a/.github/agents/project-maintainer.md b/.github/agents/project-maintainer.md index fb641f5..dabfcb4 100644 --- a/.github/agents/project-maintainer.md +++ b/.github/agents/project-maintainer.md @@ -1,215 +1,50 @@ --- name: Project Maintainer -description: >- - Expert agent for overall project management, dependency updates, CI/CD maintenance, and release coordination +description: Expert agent for SarifMark project management, dependencies, CI/CD, releases, and requirements traceability --- -# Project Maintainer Agent +# Project Maintainer - SarifMark -You are a specialized project maintainer agent for the SarifMark project. Your primary responsibility is to maintain -the overall health of the project, manage dependencies, maintain CI/CD pipelines, coordinate releases, and ensure the -project infrastructure is well-maintained. +Maintain SarifMark .NET CLI tool infrastructure, dependencies, releases, and requirements traceability. -## Responsibilities +## SarifMark-Specific -### Project Management +### Build -- Monitor and manage project dependencies -- Coordinate releases and versioning -- Maintain CI/CD pipelines and workflows -- Manage project configuration files -- Review and merge pull requests -- Triage and prioritize issues -- Ensure project documentation is up to date -- Maintain requirements in `requirements.yaml` and ensure they're linked to tests +- Targets: .NET 8.0, 9.0, 10.0 +- Zero warnings required (TreatWarningsAsErrors=true) -### Dependency Management +### Workflows (.github/workflows) -- Keep NuGet packages up to date -- Monitor for security vulnerabilities in dependencies -- Update .NET SDK versions when necessary -- Maintain dotnet tools manifest (`.config/dotnet-tools.json`) -- Review and approve dependency updates from Dependabot +- **build.yaml**: Reusable (checkout, setup .NET, restore, build Release, test, pack, upload) +- **build_on_push.yaml**: Main CI/CD (quality checks, Windows+Linux builds) -### CI/CD Maintenance +### Requirements Traceability (Critical) -- Maintain GitHub Actions workflows -- Ensure build pipelines are efficient and reliable -- Monitor build and test failures -- Update workflow configurations as needed -- Optimize build times and resource usage +- `requirements.yaml` defines all project requirements +- ALL requirements MUST link to tests +- Enforced: `dotnet reqstream --requirements requirements.yaml --tests "test-results/**/*.trx" --enforce` +- Published as PDFs: "SarifMark Requirements.pdf", "SarifMark Trace Matrix.pdf" -## Project-Specific Guidelines +### Quality Gates (Must Pass) -### Build System +1. Build (zero warnings) +2. All tests pass +3. Markdown/spell/YAML linting +4. Requirements enforcement +5. CodeQL security -- **Framework Targets**: .NET 8.0, 9.0, and 10.0 -- **Build Tool**: dotnet CLI -- **Test Framework**: MSTest -- **Package Manager**: NuGet - -### CI/CD Workflows - -Located in `.github/workflows/`: - -- **build.yaml**: Reusable build workflow - - Checkout, setup .NET, restore tools, restore dependencies - - Build (Release), test (normal verbosity), package, upload artifacts -- **build_on_push.yaml**: Main CI/CD pipeline - - Quality checks (markdown lint, spell check, YAML lint) - - Build on Windows (windows-latest) and Linux (ubuntu-latest) - - Triggers: Push, manual dispatch, weekly schedule (Monday 5PM UTC) - -### Configuration Files - -- **`.editorconfig`**: Code style rules and naming conventions -- **`.cspell.json`**: Spell checking configuration -- **`.markdownlint.json`**: Markdown linting rules -- **`.yamllint.yaml`**: YAML linting rules -- **`.config/dotnet-tools.json`**: Dotnet tools manifest -- **`DemaConsulting.SarifMark.sln`**: Solution file -- **`requirements.yaml`**: Project requirements with test linkage - -### Requirements Management - -- **Requirements File**: `requirements.yaml` defines all project requirements -- **ReqStream Tool**: Use `dotnet reqstream` to generate requirements reports and trace matrices -- **Enforcement**: The `--enforce` flag ensures all requirements are linked to passing tests -- **Documentation**: Requirements are published as "SarifMark Requirements.pdf" and "SarifMark Trace Matrix.pdf" -- **Maintenance**: Keep requirements synchronized with features and tests -- **Test Linkage**: All requirements must be linked to test methods that validate them -- **Preference**: Link to self-validation tests first, integration tests second, unit tests as last resort - -### Quality Standards - -- All builds must succeed without warnings -- All tests must pass -- Code must pass static analysis -- Documentation must be up to date -- Markdown linting must pass -- Spell checking must pass -- YAML linting must pass -- Requirements enforcement must pass - -## Release Process - -### Version Management - -- Follow semantic versioning (SemVer) -- Update version numbers in project files -- Create and tag releases appropriately -- Generate release notes - -## Quality Checks - -Before merging changes: - -1. **Build Validation**: Ensure builds succeed on all target frameworks -2. **Test Execution**: All tests pass with no failures -3. **Linting**: All linting checks pass (markdown, YAML, spell check) -4. **Static Analysis**: No new warnings or errors -5. **Code Review**: Changes reviewed by maintainers -6. **Security Scanning**: No new security vulnerabilities -7. **Requirements Enforcement**: All requirements linked to passing tests - -## Best Practices - -### Pull Request Management - -- Review PRs promptly -- Provide constructive feedback -- Ensure PRs meet quality standards -- Verify CI checks pass before merging -- Keep PRs focused and reasonably sized - -### Issue Management - -- Triage new issues quickly -- Label issues appropriately -- Prioritize based on impact and effort -- Close stale or resolved issues -- Keep issue discussions focused - -### Dependency Updates - -- Test thoroughly before merging -- Review release notes for breaking changes -- Update documentation if APIs change -- Consider impact on users - -### Communication - -- Keep stakeholders informed -- Document decisions and rationale -- Be responsive to community feedback -- Maintain professional and friendly tone - -## Boundaries - -### Do - -- Approve and merge well-reviewed PRs -- Update project dependencies regularly -- Maintain CI/CD pipelines -- Coordinate releases -- Triage and manage issues -- Ensure quality standards are met -- Update project configuration files - -### Do Not - -- Merge PRs without proper review -- Make breaking changes without discussion -- Ignore failing tests or builds -- Rush releases without proper validation -- Remove or disable quality checks -- Make unilateral architectural decisions - -## Security and Compliance - -- Monitor security advisories for dependencies -- Respond promptly to security reports -- Follow security disclosure procedures in SECURITY.md -- Ensure license compliance -- Maintain MIT license headers in source files - -## Tools and Commands - -### Build and Test +### Commands ```bash -# Restore tools -dotnet tool restore - -# Restore dependencies -dotnet restore - -# Build +dotnet tool restore && dotnet restore dotnet build --no-restore --configuration Release - -# Test -dotnet test --no-build --configuration Release --verbosity normal - -# Package +dotnet test --no-build --configuration Release dotnet pack --no-build --configuration Release ``` -### Linting Commands - -Use the project's CI pipeline configuration as the source of truth for linting commands. Linting tools and their -specific versions are managed through the CI/CD workflows. - -## Integration with Development - -- Work closely with developers on architectural decisions -- Coordinate with documentation writer for release documentation -- Collaborate with quality enforcer on quality standards -- Engage with community on feature priorities - -## Continuous Improvement +## Don't -- Regularly review and optimize build processes -- Update tooling and dependencies -- Improve documentation and processes -- Learn from issues and incidents -- Solicit feedback from contributors +- Merge without CI passing +- Ignore failing tests/builds +- Disable quality checks diff --git a/.github/agents/software-quality-enforcer.md b/.github/agents/software-quality-enforcer.md index cc2b761..943b4ca 100644 --- a/.github/agents/software-quality-enforcer.md +++ b/.github/agents/software-quality-enforcer.md @@ -1,136 +1,34 @@ --- name: Software Quality Enforcer -description: Code quality specialist focused on enforcing testing standards and code coverage, running static analysis and linting, performing code reviews and quality gates, and ensuring zero-warning builds. +description: Code quality specialist for SarifMark - enforce testing, coverage >80%, static analysis, and zero warnings --- -# Software Quality Enforcer +# Software Quality Enforcer - SarifMark -Code quality specialist focused on maintaining high standards for the SarifMark -library. Enforces testing, linting, static analysis, and code review standards. -Ensures all changes meet quality gates before merging. +Enforce quality standards for SarifMark .NET CLI tool. -## Primary Responsibilities +## Quality Gates (ALL Must Pass) -1. **Enforce Quality Standards** - - Ensure all code changes have appropriate unit tests - - Verify code coverage meets thresholds (>80%) - - Run static analyzers and ensure zero warnings - - Check that code follows .editorconfig style rules +- Zero build warnings (TreatWarningsAsErrors=true) +- All tests passing (68/68 on .NET 8/9/10) +- Code coverage >80% (currently 87.76%) +- Static analysis (Microsoft.CodeAnalysis.NetAnalyzers, SonarAnalyzer.CSharp) +- Code formatting (.editorconfig compliance) +- Markdown/spell/YAML linting +- Requirements traceability (all linked to tests) -2. **Testing Standards** - - Verify new features have comprehensive unit tests - - Ensure tests follow AAA (Arrange, Act, Assert) pattern - - Check tests are isolated and don't depend on execution order - - Validate test names are descriptive (ClassName_MethodUnderTest_Scenario_ExpectedBehavior) - - Confirm both success and failure scenarios are tested - - Verify all requirements in `requirements.yaml` are linked to tests - - Ensure requirements traceability is maintained for all changes +## SarifMark-Specific -3. **Code Review** - - Review code for adherence to C# conventions - - Check nullable reference type usage - - Verify XML documentation exists for public APIs - - Ensure no external runtime dependencies are added - - Look for security vulnerabilities +- **Test Naming**: `ClassName_MethodUnderTest_Scenario_ExpectedBehavior` (for requirements traceability) +- **Test Linkage**: All requirements MUST link to tests (prefer `SarifMark_*` self-validation) +- **XML Docs**: On ALL members (public/internal/private) with spaces after `///` +- **No external runtime deps**: Only DemaConsulting.TestResults allowed -4. **Build and CI/CD** - - Verify builds complete with zero warnings - - Ensure all tests pass on all target frameworks (.NET 8, 9, 10) - - Check SonarCloud quality gates pass - - Validate SBOM generation succeeds - -## Working Approach - -- **Run Checks First**: Always build and test before making changes -- **Use Existing Tools**: Leverage dotnet format, analyzers, and tests -- **Fix, Don't Suppress**: Address warnings rather than suppressing them -- **Be Thorough**: Check both obvious and edge cases -- **Provide Context**: Explain why changes improve quality -- **Automate**: Prefer automated checks over manual reviews - -## Commands You Use +## Commands ```bash -# Build with zero warnings -dotnet build --configuration Release - -# Run all tests -dotnet test --configuration Release - -# Check code formatting +dotnet build --configuration Release # Zero warnings required +dotnet test --configuration Release --collect "XPlat Code Coverage" dotnet format --verify-no-changes - -# Run with coverage -dotnet test --collect "XPlat Code Coverage" - -# Restore tools and dependencies -dotnet tool restore -dotnet restore - -# Validate requirements traceability dotnet reqstream --requirements requirements.yaml --tests "test-results/**/*.trx" --enforce ``` - -## Quality Gates - -All changes must pass: - -- ✅ Zero build warnings (warnings are errors) -- ✅ All unit tests passing -- ✅ Code coverage > 80% -- ✅ Static analysis (Microsoft.CodeAnalysis.NetAnalyzers, SonarAnalyzer.CSharp) -- ✅ SonarCloud quality gate -- ✅ Code formatting per .editorconfig -- ✅ Spell checking passes (cspell) -- ✅ Markdown linting passes (markdownlint) -- ✅ Requirements traceability (all requirements have tests, all tests pass) - -## Review Checklist - -For every code change, verify: - -- [ ] New code has unit tests -- [ ] Tests follow AAA pattern -- [ ] Tests are linked to requirements in `requirements.yaml` -- [ ] Public APIs have XML documentation -- [ ] No runtime dependencies added -- [ ] Nullable reference types used correctly -- [ ] No security vulnerabilities introduced -- [ ] Code follows naming conventions -- [ ] Methods are focused and concise -- [ ] No code duplication (DRY principle) -- [ ] Build succeeds with zero warnings -- [ ] All tests pass -- [ ] Requirements traceability is maintained - -## Common Issues to Catch - -- Missing unit tests for new functionality -- Insufficient test coverage -- Warnings being ignored -- Inconsistent code formatting -- Missing XML documentation -- Adding external runtime dependencies -- Security vulnerabilities (XXE, injection, etc.) -- Nullable reference type misuse -- Overly complex methods -- Code duplication - -## What NOT To Do - -- Don't suppress warnings without justification -- Don't reduce test coverage -- Don't disable or remove existing tests -- Don't add external runtime dependencies -- Don't bypass quality gates -- Don't merge changes that break builds or tests - -## Collaboration - -- Work with Documentation Writer to ensure documentation matches code quality -- Work with Project Maintainer to improve CI/CD pipelines -- Escalate architectural concerns that affect quality -- Provide constructive feedback to contributors - -Remember: Quality is not negotiable. Your role ensures that SarifMark maintains -its reputation for reliability, performance, and maintainability. diff --git a/.gitignore b/.gitignore index ad0856d..ea48538 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,8 @@ coverage/ # Test results *.trx +test-results/ +*.log # Temporary files *.tmp diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..bdfb70b --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,166 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "--configuration", + "Release", + "${workspaceFolder}/DemaConsulting.SarifMark.slnx" + ], + "problemMatcher": "$msCompile", + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "test", + "command": "dotnet", + "type": "process", + "args": [ + "test", + "--configuration", + "Release", + "${workspaceFolder}/DemaConsulting.SarifMark.slnx" + ], + "problemMatcher": "$msCompile", + "group": { + "kind": "test", + "isDefault": true + }, + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "build and test", + "dependsOn": [ + "build", + "test" + ], + "dependsOrder": "sequence", + "problemMatcher": [], + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "format", + "command": "dotnet", + "type": "process", + "args": [ + "format" + ], + "problemMatcher": [], + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "lint markdown", + "command": "npx", + "type": "shell", + "args": [ + "markdownlint-cli2", + "\"**/*.md\"", + "\"#node_modules\"" + ], + "problemMatcher": [], + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "spell check", + "command": "npx", + "type": "shell", + "args": [ + "cspell", + "\"**/*.{cs,md,json,yaml,yml}\"", + "--no-progress" + ], + "problemMatcher": [], + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "lint yaml", + "command": "npx", + "type": "shell", + "args": [ + "yamllint", + "." + ], + "problemMatcher": [], + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "lint all", + "dependsOn": [ + "format", + "lint markdown", + "spell check", + "lint yaml" + ], + "dependsOrder": "parallel", + "problemMatcher": [], + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "test with coverage", + "command": "dotnet", + "type": "process", + "args": [ + "test", + "--configuration", + "Release", + "--collect", + "XPlat Code Coverage", + "${workspaceFolder}/DemaConsulting.SarifMark.slnx" + ], + "problemMatcher": "$msCompile", + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "verify requirements", + "command": "dotnet", + "type": "shell", + "args": [ + "reqstream", + "--requirements", + "requirements.yaml", + "--tests", + "\"test-results/**/*.trx\"", + "--enforce" + ], + "problemMatcher": [], + "presentation": { + "reveal": "always", + "panel": "shared" + } + } + ] +} diff --git a/AGENTS.md b/AGENTS.md index abf26e9..be06311 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,204 +1,62 @@ -# GitHub Copilot Agents - -This document provides comprehensive guidance for GitHub Copilot agents working on the SarifMark project. - -## Overview - -GitHub Copilot agents are AI-powered assistants that help with various development tasks. This document will be -updated as agents are configured for this repository. - -## Project Overview - -SarifMark is a .NET command-line tool for creating SARIF reports from various static analysis tools. -It provides functionality to generate markdown reports that summarize code quality metrics, issues, and violations. - -### Technology Stack - -- **Language**: C# 12 -- **Framework**: .NET 8.0, 9.0, and 10.0 -- **Testing Framework**: MSTest -- **Build System**: dotnet CLI -- **Package Manager**: NuGet - -## Project Structure - -```text -SarifMark/ -├── .github/ # GitHub Actions workflows -│ ├── agents/ # Agent configurations -│ ├── ISSUE_TEMPLATE/ # Issue templates -│ └── workflows/ -│ ├── build.yaml # Reusable build workflow -│ └── build_on_push.yaml # Main CI/CD pipeline -├── src/ # Source code -│ └── DemaConsulting.SarifMark/ # Main application project -├── test/ # Test projects -│ └── DemaConsulting.SarifMark.Tests/ # Test project -├── .cspell.json # Spell checking configuration -├── .editorconfig # Code style configuration -├── .markdownlint.json # Markdown linting rules -├── .yamllint.yaml # YAML linting rules -├── AGENTS.md # This file -├── CODE_OF_CONDUCT.md # Code of Conduct -├── LICENSE # MIT License -├── README.md # Project documentation -├── requirements.yaml # Project requirements -└── SECURITY.md # Security policy -``` - -### Critical Files - -- **`.editorconfig`**: Defines code style rules, naming conventions, and formatting standards -- **`.cspell.json`**: Contains spell-checking configuration and custom dictionary -- **`.markdownlint.json`**: Markdown linting rules -- **`.yamllint.yaml`**: YAML linting rules -- **`DemaConsulting.SarifMark.sln`**: Solution file containing all projects -- **`requirements.yaml`**: Project requirements with test linkage - -## Requirements Management - -SarifMark uses DemaConsulting.ReqStream for requirements management: - -- **Requirements File**: `requirements.yaml` contains all project requirements -- **Test Linkage**: All requirements must be linked to test methods that validate them -- **Self-Validation**: Prefer linking to self-validation tests (e.g., `SarifMark_*`) over unit tests -- **Enforcement**: Requirements are enforced via `dotnet reqstream --enforce` in CI/CD -- **Documentation**: Requirements are published as "SarifMark Requirements.pdf" and "SarifMark Trace Matrix.pdf" -- **Updates**: When adding features, add corresponding requirements; when adding tests, link them to requirements - -## Testing Guidelines - -- **Test Framework**: MSTest v4 (Microsoft.VisualStudio.TestTools.UnitTesting) -- **Test File Naming**: `[Component]Tests.cs` (e.g., `ProgramTests.cs`) -- **Test Method Naming**: `ClassName_MethodUnderTest_Scenario_ExpectedBehavior` format - - Example: `Program_Main_NoArguments_ReturnsSuccess` clearly indicates testing the `Program.Main` method - - This pattern makes test intent clear for requirements traceability -- **MSTest v4 APIs**: Use modern assertions: - - `Assert.HasCount(collection, expectedCount)` instead of `Assert.AreEqual(count, collection.Count)` - - `Assert.IsEmpty(collection)` instead of `Assert.AreEqual(0, collection.Count)` - - `Assert.DoesNotContain(item, collection)` for negative checks -- **Console Testing**: Save and restore `Console.Out` in tests that modify console output: - - ```csharp - var originalOut = Console.Out; - try { /* test code */ } - finally { Console.SetOut(originalOut); } - ``` - -- **All tests must pass** before merging changes -- **No warnings allowed** in test builds +# Agent Quick Reference -## Code Style and Conventions +Project-specific guidance for agents working on SarifMark - a .NET CLI tool for creating markdown reports from SARIF files. -### Naming Conventions +## Tech Stack -- **Interfaces**: Must begin with `I` (e.g., `IReportGenerator`) -- **Classes, Structs, Enums**: PascalCase -- **Methods, Properties**: PascalCase -- **Parameters, Local Variables**: camelCase +- C# 12, .NET 8.0/9.0/10.0, MSTest, dotnet CLI, NuGet -### Code Organization +## Key Files -- **Namespace Declarations**: Use file-scoped namespaces (C# 10+) -- **Using Directives**: Sort system directives first -- **Braces**: Required for all control statements -- **Indentation**: 4 spaces for C#, 2 spaces for YAML/JSON/XML -- **Encoding**: UTF-8 with BOM, LF line endings with final newline +- **`requirements.yaml`** - All requirements with test linkage (enforced via `dotnet reqstream --enforce`) +- **`.editorconfig`** - Code style (file-scoped namespaces, 4-space indent, UTF-8+BOM, LF endings) +- **`.cspell.json`, `.markdownlint.json`, `.yamllint.yaml`** - Linting configs -### Documentation and Comments +## Requirements (SarifMark-Specific) -- **Copyright Headers**: All source files must include the MIT license header -- **XML Documentation**: Use triple-slash comments (`///`) for all public, internal, and private members - - **IMPORTANT**: Summary blocks must be indented with spaces after `///` +- Link ALL requirements to tests (prefer `SarifMark_*` self-validation over unit tests) +- Enforced in CI: `dotnet reqstream --requirements requirements.yaml --tests "test-results/**/*.trx" --enforce` +- When adding features: add requirement + link to test - ```csharp - /// - /// This is the correct indentation format for summary blocks. - /// - ``` +## Testing (SarifMark-Specific) -- **Error Handling Patterns**: - - Argument parsing: Throw `ArgumentException` with descriptive messages - - Runtime errors during execution: Use `InvalidOperationException` - - Write methods (WriteLine/WriteError) are for output AFTER successful parsing -- **Code Reusability**: Create properties or methods to avoid code duplication +- **Test Naming**: `ClassName_MethodUnderTest_Scenario_ExpectedBehavior` (for requirements traceability) +- **MSTest v4**: Use `Assert.HasCount()`, `Assert.IsEmpty()`, `Assert.DoesNotContain()` (not old APIs) +- **Console Tests**: Always save/restore `Console.Out` in try/finally -## Quality Standards +## Code Style (SarifMark-Specific) -- **Static Analysis**: Built-in .NET analyzers enforce code style, naming rules, and nullable reference types -- **Documentation**: - - README.md uses absolute URLs (included in NuGet package) - - Other markdown files use link references: `[text][ref]` with `[ref]: url` at end -- **Linting**: - - **Markdown**: Must pass markdownlint (max line length: 120 chars) - - Lists must be surrounded by blank lines (MD032) - - Run locally: Check CI workflow for markdownlint-cli2-action usage - - **Spell Check**: Must pass cspell (custom dictionary in `.cspell.json`) - - Add project-specific terms to the custom dictionary if needed - - **YAML**: Must pass yamllint (2-space indentation, max line length: 120 chars) - - **All linting must pass locally before committing** - CI will reject changes with linting errors +- **XML Docs**: On ALL members (public/internal/private) with spaces after `///` in summaries +- **Errors**: `ArgumentException` for parsing, `InvalidOperationException` for runtime, Write* only after success +- **No code duplication**: Extract to properties/methods -## CI/CD Pipelines +## Linting (SarifMark-Specific) -The project uses GitHub Actions workflows in `.github/workflows/`: +- **README.md**: Absolute URLs only (shipped in NuGet package) +- **Other .md**: Reference-style links `[text][ref]` with `[ref]: url` at end +- **All linters must pass locally**: markdownlint, cspell, yamllint (see CI workflows for commands) -- **build_on_push.yaml**: Runs quality checks, builds on Windows and Linux -- **build.yaml**: Reusable workflow for restore, build, test, and package - -Build commands: +## Build & Quality (Quick Reference) ```bash -dotnet restore # Restore dependencies -dotnet build --no-restore --configuration Release -dotnet test --no-build --configuration Release --verbosity normal -dotnet pack --no-build --configuration Release +# Standard build/test +dotnet build --configuration Release && dotnet test --configuration Release + +# Pre-finalization checklist (in order): +# 1. Build/test (zero warnings required) +# 2. code_review tool +# 3. codeql_checker tool +# 4. All linters (markdownlint, cspell, yamllint) +# 5. Requirements: dotnet reqstream --requirements requirements.yaml --tests "test-results/**/*.trx" --enforce ``` -## Pre-Finalization Quality Checks - -Before completing any task, you **MUST** perform these checks in order and ensure they all pass: - -1. **Build and Test**: Run `dotnet build --configuration Release && dotnet test --configuration Release` - all tests - must pass with zero warnings -2. **Code Review**: Use `code_review` tool and address all valid concerns -3. **Security Scanning**: Use `codeql_checker` tool after code review - must report zero vulnerabilities -4. **Linting**: Run all linters locally and fix any issues before pushing changes: - - **Markdown**: Run markdownlint on all changed `.md` files - must pass with zero errors - - **Spell Check**: Run cspell on all changed files - must pass with zero errors - - **YAML**: Run yamllint on all changed `.yaml` or `.yml` files - must pass with zero errors - - These linters run in CI and will fail the build if not passing -5. **Requirements Enforcement**: Verify all requirements have test linkage by running - `dotnet reqstream --requirements requirements.yaml --tests "test-results/**/*.trx" --enforce` - must pass - -## Project-Specific Guidelines - -### Key Decisions from Recent Reviews - -These patterns emerged from code review feedback and should be followed: - -1. **XmlDoc Formatting**: Always indent summary content with spaces after `///` -2. **Error Handling**: Throw exceptions during parsing; use Write methods only after successful parsing -3. **Code Reuse**: Extract repeated code into properties or methods -4. **Console Testing**: Always save/restore `Console.Out` in try/finally blocks -5. **Modern Test APIs**: Prefer MSTest v4 assertions (HasCount, IsEmpty, DoesNotContain) - -### What NOT to Do - -- Don't delete or modify working code unless fixing a security vulnerability -- Don't remove or modify existing tests unless directly related to your changes -- Don't commit build artifacts (`bin/`, `obj/`, `node_modules/`) -- Don't use force push (`git reset`, `git rebase`) -- Don't create temporary files in the repository (use `/tmp` instead) -- Don't make changes to `.github/agents/` files (for other agents only) - -## Available Agents +## Custom Agents -The following custom agents are configured for this repository. Each agent file contains detailed guidelines, -responsibilities, and project-specific conventions. +Delegate tasks to specialized agents for better results: -- **Documentation Writer** (`.github/agents/documentation-writer.md`) - Expert agent for creating, updating, and - maintaining project documentation -- **Project Maintainer** (`.github/agents/project-maintainer.md`) - Expert agent for overall project management, - dependency updates, CI/CD maintenance, and release coordination -- **Software Quality Enforcer** (`.github/agents/software-quality-enforcer.md`) - Expert agent for enforcing code - quality standards, testing requirements, and quality gates +- **documentation-writer** - Invoke for: documentation updates/reviews, requirements.yaml changes, + markdown/spell/YAML linting +- **project-maintainer** - Invoke for: dependency updates, CI/CD maintenance, releases, requirements + traceability enforcement +- **software-quality-enforcer** - Invoke for: code quality reviews, test coverage verification (>80%), + static analysis, zero-warning builds, requirements test quality diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..dc67e86 --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,99 @@ +# Development Quick Start + +Quick reference for developers and AI agents working on SarifMark. + +## Prerequisites + +- [.NET SDK 8.0, 9.0, or 10.0][dotnet-sdk] +- [Node.js][nodejs] (for linting tools) + +## Quick Commands + +```bash +# First time setup +npm install # Install linting tools +dotnet tool restore # Install .NET tools +dotnet restore # Restore dependencies + +# Build and test +dotnet build --configuration Release # Build (zero warnings required) +dotnet test --configuration Release # Run all tests + +# Code quality +dotnet format # Format code +dotnet format --verify-no-changes # Verify formatting +npx markdownlint-cli2 "**/*.md" # Lint markdown +npx cspell "**/*.{cs,md,json,yaml,yml}" # Spell check +npx yamllint . # Lint YAML + +# Requirements traceability +dotnet test --configuration Release --logger "trx;LogFileName=test-results.trx" +dotnet reqstream --requirements requirements.yaml --tests "test-results/**/*.trx" --enforce + +# Coverage +dotnet test --configuration Release --collect "XPlat Code Coverage" + +# Package +dotnet pack --configuration Release +``` + +## Project Structure + +```text +SarifMark/ +├── src/DemaConsulting.SarifMark/ # Main CLI tool +├── test/DemaConsulting.SarifMark.Tests/ # Tests +├── requirements.yaml # Requirements (linked to tests) +├── .editorconfig # Code style rules +└── .github/workflows/ # CI/CD pipelines +``` + +## Code Standards + +- **Test Naming**: `ClassName_MethodUnderTest_Scenario_ExpectedBehavior` +- **XML Docs**: Required on ALL members (public/internal/private) +- **Requirements**: All features must have requirements linked to tests +- **Zero Warnings**: Build must complete with zero warnings +- **Coverage**: Maintain >80% code coverage + +## Pre-Commit Checklist + +1. ✅ `dotnet build --configuration Release` (zero warnings) +2. ✅ `dotnet test --configuration Release` (all pass) +3. ✅ `dotnet format --verify-no-changes` (formatting) +4. ✅ `npx markdownlint-cli2 "**/*.md"` (markdown) +5. ✅ `npx cspell "**/*.{cs,md,json,yaml,yml}"` (spelling) +6. ✅ Requirements enforcement passes + +## Common Tasks + +### Adding a Feature + +1. Add requirement to `requirements.yaml` +2. Write tests (link to requirement) +3. Implement feature +4. Update documentation +5. Run pre-commit checklist + +### Fixing a Bug + +1. Write failing test +2. Fix bug +3. Verify test passes +4. Run pre-commit checklist + +### Updating Dependencies + +1. Update package references +2. Run full build and test suite +3. Update `requirements.yaml` if needed +4. Check for security vulnerabilities + +## Resources + +- [AGENTS.md](AGENTS.md) - Agent-specific guidance +- [CONTRIBUTING.md](CONTRIBUTING.md) - Detailed contribution guide +- [README.md](README.md) - Project overview + +[dotnet-sdk]: https://dotnet.microsoft.com/download +[nodejs]: https://nodejs.org/ diff --git a/README.md b/README.md index 70c0f59..71f23c2 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,30 @@ Run the tool: dotnet sarifmark --version ``` +### Update + +To update to the latest version: + +```bash +# Global installation +dotnet tool update --global DemaConsulting.SarifMark + +# Local installation +dotnet tool update DemaConsulting.SarifMark +``` + +### Compatibility + +| Component | Version | Status | +| :-------- | :------ | :----- | +| .NET SDK | 8.0 | ✅ Supported | +| .NET SDK | 9.0 | ✅ Supported | +| .NET SDK | 10.0 | ✅ Supported | +| SARIF Format | 2.1.0 | ✅ Supported | +| OS | Windows | ✅ Supported | +| OS | Linux | ✅ Supported | +| OS | macOS | ✅ Supported | + ## Usage ### Basic Usage diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..6ea0688 --- /dev/null +++ b/build.bat @@ -0,0 +1,12 @@ +@echo off +REM Build and test SarifMark (Windows) + +echo Building SarifMark... +dotnet build --configuration Release +if %errorlevel% neq 0 exit /b %errorlevel% + +echo Running tests... +dotnet test --configuration Release --verbosity normal +if %errorlevel% neq 0 exit /b %errorlevel% + +echo Build and test completed successfully! diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..03d8518 --- /dev/null +++ b/build.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# Build and test SarifMark + +set -e # Exit on error + +echo "🔧 Building SarifMark..." +dotnet build --configuration Release + +echo "✅ Running tests..." +dotnet test --configuration Release --verbosity normal + +echo "✨ Build and test completed successfully!" diff --git a/docs/guide/guide.md b/docs/guide/guide.md index 0f9cd6a..0420e04 100644 --- a/docs/guide/guide.md +++ b/docs/guide/guide.md @@ -228,6 +228,89 @@ SarifMark uses the following exit codes: - `1`: Error (invalid arguments, file not found, processing error) - Non-zero (with `--enforce`): Issues found in SARIF file +## Frequently Asked Questions + +### What is SARIF? + +SARIF (Static Analysis Results Interchange Format) is a standard format for the output of static analysis tools. It's +designed to be easily integrated into development workflows and provides a consistent structure for representing +analysis results from different tools. + +For more information, visit the [SARIF website](https://sarifweb.azurewebsites.net/). + +### Which static analysis tools produce SARIF output? + +Many popular static analysis tools support SARIF output, including: + +- **CodeQL** - Security and quality analysis +- **SonarQube** - Code quality and security analysis +- **ESLint** - JavaScript linting (with SARIF formatter) +- **Pylint** - Python linting (with SARIF converter) +- **Semgrep** - Pattern-based code analysis +- **Checkmarx** - Security scanning +- **Trivy** - Container vulnerability scanning + +Check your tool's documentation for SARIF export options. + +### Can I process multiple SARIF files at once? + +Currently, SarifMark processes one SARIF file at a time. To process multiple files, run the tool multiple times with +different input and output files. You can combine the reports manually or use a script to merge them. + +### How do I use SarifMark in a CI/CD pipeline? + +See the [Integration Examples](#integration-examples) section above for CI/CD integration examples. The key steps are: + +1. Run your static analysis tool to generate a SARIF file +2. Install SarifMark in your pipeline +3. Run SarifMark to generate a report +4. Optionally use `--enforce` to fail the build if issues are found + +### What happens when I use the --enforce flag? + +When you use the `--enforce` flag, SarifMark will: + +- Process the SARIF file normally +- Generate any requested reports +- Return a non-zero exit code if the SARIF file contains any issues + +This is useful in CI/CD pipelines to fail builds when quality issues are detected. + +### Can I customize the report format? + +Yes, you can customize: + +- **Heading**: Use `--heading "Custom Title"` to set a custom report heading +- **Header Depth**: Use `--report-depth 2` to adjust the markdown header level (useful when including the report in + a larger document) + +The report content format is standardized but these options allow you to integrate reports into different documentation +structures. + +### What .NET versions are supported? + +SarifMark supports .NET 8.0, 9.0, and 10.0. You need at least one of these SDK versions installed to use the tool. +The tool is built as a multi-targeted package, so it will automatically use the appropriate version based on your +installed .NET runtime. + +### How do I update SarifMark? + +To update to the latest version: + +```bash +# Global installation +dotnet tool update --global DemaConsulting.SarifMark + +# Local installation +dotnet tool update DemaConsulting.SarifMark +``` + +### Where can I find more help? + +- **GitHub Issues**: +- **GitHub Discussions**: +- **Documentation**: + ## Troubleshooting ### SARIF File Not Found diff --git a/lint.bat b/lint.bat new file mode 100644 index 0000000..eb048bf --- /dev/null +++ b/lint.bat @@ -0,0 +1,20 @@ +@echo off +REM Run all linters for SarifMark (Windows) + +echo Checking markdown... +call npx markdownlint-cli2 "**/*.md" "#node_modules" +if %errorlevel% neq 0 exit /b %errorlevel% + +echo Checking spelling... +call npx cspell "**/*.{cs,md,json,yaml,yml}" --no-progress +if %errorlevel% neq 0 exit /b %errorlevel% + +echo Checking YAML... +call npx yamllint . +if %errorlevel% neq 0 exit /b %errorlevel% + +echo Checking code formatting... +dotnet format --verify-no-changes +if %errorlevel% neq 0 exit /b %errorlevel% + +echo All linting passed! diff --git a/lint.sh b/lint.sh new file mode 100755 index 0000000..e096d23 --- /dev/null +++ b/lint.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +# Run all linters for SarifMark + +set -e # Exit on error + +echo "📝 Checking markdown..." +npx markdownlint-cli2 "**/*.md" "#node_modules" + +echo "🔤 Checking spelling..." +npx cspell "**/*.{cs,md,json,yaml,yml}" --no-progress + +echo "📋 Checking YAML..." +npx yamllint . + +echo "🎨 Checking code formatting..." +dotnet format --verify-no-changes + +echo "✨ All linting passed!" diff --git a/test/DemaConsulting.SarifMark.Tests/PathHelpersTests.cs b/test/DemaConsulting.SarifMark.Tests/PathHelpersTests.cs index de29a70..628c305 100644 --- a/test/DemaConsulting.SarifMark.Tests/PathHelpersTests.cs +++ b/test/DemaConsulting.SarifMark.Tests/PathHelpersTests.cs @@ -54,7 +54,7 @@ public void PathHelpers_SafePathCombine_PathWithParentDirectory_ThrowsArgumentEx var relativePath = "../etc/passwd"; // Act & Assert - var exception = Assert.Throws(() => + var exception = Assert.Throws(() => PathHelpers.SafePathCombine(basePath, relativePath)); Assert.Contains("Invalid path component", exception.Message); Assert.AreEqual("relativePath", exception.ParamName); @@ -71,7 +71,7 @@ public void PathHelpers_SafePathCombine_PathWithDoubleDots_ThrowsArgumentExcepti var relativePath = "documents/../../../etc/passwd"; // Act & Assert - var exception = Assert.Throws(() => + var exception = Assert.Throws(() => PathHelpers.SafePathCombine(basePath, relativePath)); Assert.Contains("Invalid path component", exception.Message); } @@ -85,7 +85,7 @@ public void PathHelpers_SafePathCombine_AbsolutePath_ThrowsArgumentException() // Test Unix absolute path var unixBasePath = "/home/user"; var unixRelativePath = "/etc/passwd"; - var unixException = Assert.Throws(() => + var unixException = Assert.Throws(() => PathHelpers.SafePathCombine(unixBasePath, unixRelativePath)); Assert.Contains("Invalid path component", unixException.Message); @@ -94,7 +94,7 @@ public void PathHelpers_SafePathCombine_AbsolutePath_ThrowsArgumentException() { var windowsBasePath = "C:\\Users\\User"; var windowsRelativePath = "C:\\Windows\\System32"; - var windowsException = Assert.Throws(() => + var windowsException = Assert.Throws(() => PathHelpers.SafePathCombine(windowsBasePath, windowsRelativePath)); Assert.Contains("Invalid path component", windowsException.Message); } diff --git a/test/DemaConsulting.SarifMark.Tests/SarifResultsTests.cs b/test/DemaConsulting.SarifMark.Tests/SarifResultsTests.cs index c4af6eb..f5e8c3b 100644 --- a/test/DemaConsulting.SarifMark.Tests/SarifResultsTests.cs +++ b/test/DemaConsulting.SarifMark.Tests/SarifResultsTests.cs @@ -312,15 +312,15 @@ public void SarifResults_Read_WithResults_ReturnsValidResults() Assert.AreEqual("1.0.0", results.ToolVersion); Assert.AreEqual(3, results.ResultCount); Assert.HasCount(3, results.Results); - + Assert.AreEqual("TEST001", results.Results[0].RuleId); Assert.AreEqual("error", results.Results[0].Level); Assert.AreEqual("Error 1", results.Results[0].Message); - + Assert.AreEqual("TEST002", results.Results[1].RuleId); Assert.AreEqual("warning", results.Results[1].Level); Assert.AreEqual("Warning 1", results.Results[1].Message); - + Assert.AreEqual("TEST003", results.Results[2].RuleId); Assert.AreEqual("note", results.Results[2].Level); Assert.AreEqual("Note 1", results.Results[2].Message); @@ -967,10 +967,10 @@ public void SarifResults_Read_WithSuppressedResults_ExcludesSuppressedResults() Assert.AreEqual("1.0.0", results.ToolVersion); Assert.AreEqual(2, results.ResultCount); Assert.HasCount(2, results.Results); - + Assert.AreEqual("TEST001", results.Results[0].RuleId); Assert.AreEqual("Unsuppressed warning", results.Results[0].Message); - + Assert.AreEqual("TEST003", results.Results[1].RuleId); Assert.AreEqual("Another unsuppressed error", results.Results[1].Message); }