diff --git a/.cspell.json b/.cspell.json index e5522e4..8fbe61c 100644 --- a/.cspell.json +++ b/.cspell.json @@ -2,24 +2,38 @@ "version": "0.2", "language": "en", "words": [ + "Anson", + "Blockquotes", "buildmark", "BuildMark", "buildnotes", + "camelcase", + "Checkmarx", "codeql", "CodeQL", "copilot", "creatordate", "cspell", "csproj", + "dbproj", + "dcterms", "Dema", "demaconsulting", "DEMACONSULTINGNUGETKEY", "Dependabot", "dependabot", + "doctitle", "dotnet", "editorconfig", + "filepart", + "fsproj", + "Gidget", + "gitattributes", "ibiqlik", + "LINQ", + "maintainer", "markdownlint", + "mermaid", "mstest", "myterm", "ncipollo", @@ -28,14 +42,29 @@ "oneline", "opencover", "pandoc", + "pagetitle", + "Pylint", + "Qube", "reqstream", + "SarifMark", "SBOM", "sbom", + "Semgrep", "semver", "slnx", "snupkg", + "sonarmark", + "SonarMark", + "SonarQube", + "spdx", + "streetsidesoftware", + "TMPL", "tracematrix", + "triaging", + "Trivy", "trx", + "vbproj", + "vcxproj", "versionmark", "Weasyprint", "yamllint" diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index ad3c25c..c52d457 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -28,6 +28,9 @@ Before submitting this pull request, ensure you have completed the following: - [ ] Code builds successfully: `dotnet build --configuration Release` - [ ] All tests pass: `dotnet test --configuration Release` +- [ ] Self-validation tests pass: + `dotnet run --project src/DemaConsulting.BuildMark --configuration Release --framework net10.0` + `--no-build -- --validate` - [ ] Code produces zero warnings ### Code Quality diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 437409d..be846ee 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -325,6 +325,7 @@ jobs: contents: read steps: + # === CHECKOUT AND INSTALL DEPENDENCIES === - name: Checkout uses: actions/checkout@v6 @@ -379,6 +380,7 @@ jobs: pattern: 'version-capture-*' continue-on-error: true + # === GENERATE MARKDOWN REPORTS === - name: Generate Requirements Report and Trace Matrix run: > dotnet reqstream @@ -462,6 +464,7 @@ jobs: echo "=== Build Notes Report ===" cat docs/buildnotes.md + # === GENERATE HTML AND PDF DOCUMENTS === - name: Generate Build Notes HTML with Pandoc shell: bash run: > @@ -475,6 +478,7 @@ jobs: - name: Convert Build Notes HTML to PDF with Weasyprint run: > dotnet weasyprint + --pdf-variant pdf/a-3u docs/buildnotes/buildnotes.html "docs/BuildMark Build Notes.pdf" @@ -491,6 +495,7 @@ jobs: - name: Convert User Guide HTML to PDF with Weasyprint run: > dotnet weasyprint + --pdf-variant pdf/a-3u docs/guide/guide.html "docs/BuildMark User Guide.pdf" @@ -507,6 +512,7 @@ jobs: - name: Generate Requirements PDF with Weasyprint run: > dotnet weasyprint + --pdf-variant pdf/a-3u docs/requirements/requirements.html "docs/BuildMark Requirements.pdf" @@ -523,6 +529,7 @@ jobs: - name: Generate Trace Matrix PDF with Weasyprint run: > dotnet weasyprint + --pdf-variant pdf/a-3u docs/tracematrix/tracematrix.html "docs/BuildMark Trace Matrix.pdf" @@ -539,6 +546,7 @@ jobs: - name: Convert Requirements Justifications HTML to PDF with Weasyprint run: > dotnet weasyprint + --pdf-variant pdf/a-3u docs/justifications/justifications.html "docs/BuildMark Requirements Justifications.pdf" @@ -555,9 +563,11 @@ jobs: - name: Convert Code Quality HTML to PDF with Weasyprint run: > dotnet weasyprint + --pdf-variant pdf/a-3u docs/quality/quality.html "docs/BuildMark Code Quality.pdf" + # === UPLOAD ARTIFACTS === - name: Upload Document Artifacts uses: actions/upload-artifact@v7 with: diff --git a/.gitignore b/.gitignore index aab056b..a6d25c9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,37 @@ .vs *.bak *.user +*.suo +*.userosscache +*.sln.docstates +mono_crash.* +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Xx]64/ +[Xx]86/ +[Ww]in32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ bin/ obj/ -TestResults/ + +# ReSharper +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JetBrains Rider +.idea/ +*.sln.iml + +# NuGet packages +*.nupkg +*.snupkg +**/packages/* # Code coverage reports coverage/ @@ -13,6 +40,8 @@ coverage/ *.opencover.xml # Test results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* *.trx test-results/ *.log @@ -25,21 +54,21 @@ test-results/ node_modules/ package-lock.json +# Python +__pycache__/ +*.py[cod] + # Generated documentation -docs/*.pdf -docs/guide/*.html +docs/**/*.html +docs/**/*.pdf +!docs/template/** docs/requirements/requirements.md -docs/requirements/*.html docs/tracematrix/tracematrix.md -docs/tracematrix/*.html docs/justifications/justifications.md -docs/justifications/*.html docs/quality/sonar-quality.md docs/quality/codeql-quality.md -docs/quality/*.html docs/buildnotes.md docs/buildnotes/versions.md -docs/buildnotes/*.html # VersionMark captures (generated during CI/CD) versionmark-*.json diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..9ebdf1e --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,102 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "command": "dotnet build --configuration Release", + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "reveal": "always", + "panel": "shared" + }, + "problemMatcher": "$msCompile" + }, + { + "label": "validate", + "type": "shell", + "command": "dotnet run --project src/DemaConsulting.BuildMark --configuration Release --framework net10.0 --no-build -- --validate", + "group": { + "kind": "test", + "isDefault": true + }, + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "build and validate", + "dependsOn": ["build", "validate"], + "dependsOrder": "sequence", + "group": "build", + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "format", + "type": "shell", + "command": "dotnet format", + "group": "none", + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "lint markdown", + "type": "shell", + "command": "npx markdownlint-cli2 \"**/*.md\"", + "group": "none", + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "spell check", + "type": "shell", + "command": "npx cspell \"**/*.{md,cs}\"", + "group": "none", + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "lint yaml", + "type": "shell", + "command": "yamllint .", + "group": "none", + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "lint all", + "dependsOn": ["format", "lint markdown", "spell check", "lint yaml"], + "dependsOrder": "parallel", + "group": "none", + "presentation": { + "reveal": "always", + "panel": "shared" + } + }, + { + "label": "verify requirements", + "type": "shell", + "command": "dotnet reqstream --requirements requirements.yaml --tests \"test-results/**/*.trx\" --enforce", + "group": "none", + "presentation": { + "reveal": "always", + "panel": "shared" + } + } + ] +} diff --git a/AGENTS.md b/AGENTS.md index b73cb74..4ce91e4 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,13 +13,13 @@ Project-specific guidance for agents working on BuildMark - a .NET CLI tool for ## Tech Stack -- C# 12, .NET 8.0/9.0/10.0, MSTest, dotnet CLI, NuGet +- C# (latest), .NET 8.0/9.0/10.0, MSTest, dotnet CLI, NuGet ## Key Files - **`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 +- **`.editorconfig`** - Code style (file-scoped namespaces, 4-space indent, UTF-8, LF endings) +- **`.cspell.json`, `.markdownlint-cli2.jsonc`, `.yamllint.yaml`** - Linting configs ## Requirements @@ -107,3 +107,13 @@ When agents need to write report files to communicate with each other or the use - Excluded from git (via .gitignore) - Excluded from markdown linting - Excluded from spell checking + +## Markdown Link Style + +- **AI agent markdown files** (`.github/agents/*.md`): Use inline links `[text](url)` so URLs are visible in agent context +- **README.md**: Use absolute URLs (shipped in NuGet package) +- **All other markdown files**: Use reference-style links `[text][ref]` with `[ref]: url` at document end + +## Notable Absent Files + +- **CHANGELOG.md**: Not present - changes are captured in the auto-generated build notes diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7c54d30..2797aa0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -95,7 +95,7 @@ This project enforces code style through `.editorconfig`. Key requirements: - **Indentation**: 4 spaces for C#, 2 spaces for YAML/JSON/XML - **Line Endings**: LF (Unix-style) -- **Encoding**: UTF-8 with BOM +- **Encoding**: UTF-8 - **Namespaces**: Use file-scoped namespace declarations - **Braces**: Required for all control statements - **Naming Conventions**: @@ -142,7 +142,7 @@ Examples: - Write tests that are clear and focused - Use modern MSTest v4 assertions: - - `Assert.HasCount(collection, expectedCount)` + - `Assert.HasCount(expectedCount, collection)` - `Assert.IsEmpty(collection)` - `Assert.DoesNotContain(item, collection)` - Always clean up resources (use `try/finally` for console redirection) @@ -188,6 +188,14 @@ dotnet test --filter "FullyQualifiedName~YourTestName" dotnet test --collect "XPlat Code Coverage" ``` +### Self-Validation Tests + +```bash +# Run self-validation tests +dotnet run --project src/DemaConsulting.BuildMark \ + --configuration Release --framework net10.0 --no-build -- --validate +``` + ## Documentation ### Markdown Guidelines @@ -199,6 +207,7 @@ All markdown files must follow these rules (enforced by markdownlint): - Lists must be surrounded by blank lines - Use reference-style links: `[text][ref]` with `[ref]: url` at document end - **Exception**: `README.md` uses absolute URLs (it's included in the NuGet package) +- **Exception**: `.github/agents/*.md` files use inline links so URLs are visible in agent context ### Spell Checking @@ -253,6 +262,31 @@ Maintain code coverage above 80%: dotnet test --collect "XPlat Code Coverage" ``` +## Requirements Management + +BuildMark uses [DemaConsulting.ReqStream][reqstream] for requirements traceability: + +- All requirements are defined in `requirements.yaml` +- Each requirement must be linked to at least one test case +- Run `dotnet reqstream` to generate the requirements documentation +- Use the `--enforce` flag in CI to ensure all requirements are covered + +When adding new features: + +1. Add the requirement to `requirements.yaml` +2. Write tests that validate the requirement +3. Link the tests to the requirement in `requirements.yaml` + +## Release Process + +Releases follow this process: + +1. Create a release issue to track the release +2. Update version references as needed +3. Create a pull request with the release changes +4. Merge the pull request after review +5. Create a GitHub release with the new version tag — CI/CD will automatically build and publish the NuGet package + ## Pull Request Process 1. **Update Documentation**: Ensure all documentation is updated to reflect your changes @@ -266,12 +300,17 @@ dotnet test --collect "XPlat Code Coverage" If you need help or have questions: -- **GitHub Issues**: For bug reports and feature requests -- **GitHub Discussions**: For general questions and discussions +- **GitHub Issues**: For bug reports and feature requests — [open an issue][issues] +- **GitHub Discussions**: For general questions and discussions — [start a discussion][discussions] - **Pull Request Comments**: For questions about specific code changes +- **Security Vulnerabilities**: Please review the [Security Policy][security] before reporting Thank you for contributing to BuildMark! [code-of-conduct]: https://github.com/demaconsulting/BuildMark/blob/main/CODE_OF_CONDUCT.md [dotnet-download]: https://dotnet.microsoft.com/download -[csharp-conventions]: https://docs.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions +[csharp-conventions]: https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions +[reqstream]: https://github.com/demaconsulting/ReqStream +[discussions]: https://github.com/demaconsulting/BuildMark/discussions +[issues]: https://github.com/demaconsulting/BuildMark/issues +[security]: https://github.com/demaconsulting/BuildMark/blob/main/SECURITY.md diff --git a/README.md b/README.md index e26163c..80a2b34 100644 --- a/README.md +++ b/README.md @@ -146,25 +146,42 @@ buildmark --validate buildmark --validate --results validation-results.trx ``` -### Self-Validation Tests +## Self Validation -BuildMark includes built-in self-validation tests that verify the tool's functionality without requiring external -repositories or services. These tests use mock data to validate core features and generate test result files in TRX -or JUnit format. +Running self-validation produces a report containing the following information: -The self-validation suite includes tests that verify: +```text +# DEMA Consulting BuildMark Self-validation + +| Information | Value | +| :------------------ | :------------------------------------------------- | +| BuildMark Version | | +| Machine Name | | +| OS Version | | +| DotNet Runtime | | +| Time Stamp | UTC | + +✓ BuildMark_MarkdownReportGeneration - Passed +✓ BuildMark_GitIntegration - Passed +✓ BuildMark_IssueTracking - Passed +✓ BuildMark_KnownIssuesReporting - Passed + +Total Tests: 4 +Passed: 4 +Failed: 0 +``` -- Version tag parsing and comparison -- Build information extraction from repositories -- Markdown report generation -- GitHub repository connector functionality -- Mock repository connector functionality +Each test in the report proves: -These tests provide evidence of the tool's functionality and are particularly useful for: +- **`BuildMark_MarkdownReportGeneration`** - Markdown report is correctly generated from mock data. +- **`BuildMark_GitIntegration`** - Git repository connector reads version tags and commits. +- **`BuildMark_IssueTracking`** - GitHub issue and pull request tracking works correctly. +- **`BuildMark_KnownIssuesReporting`** - Known issues are correctly included when requested. -- Verifying the installation is working correctly -- Running automated tests in CI/CD pipelines without requiring repository access -- Generating test evidence for compliance and traceability requirements +See the [User Guide](https://github.com/demaconsulting/BuildMark/blob/main/docs/guide/guide.md) for more details +on the self-validation tests. + +On validation failure the tool will exit with a non-zero exit code. ## Report Format @@ -219,6 +236,8 @@ For bug reports, feature requests, and questions, please use This project is licensed under the MIT License - see the [LICENSE](https://github.com/demaconsulting/BuildMark/blob/main/LICENSE) file for details. +By contributing to this project, you agree that your contributions will be licensed under the MIT License. + ## Support - 🐛 **Report Bugs**: [GitHub Issues](https://github.com/demaconsulting/BuildMark/issues) diff --git a/SECURITY.md b/SECURITY.md index f6484a5..aff339b 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -7,7 +7,6 @@ BuildMark follows semantic versioning. Security updates are provided for the fol | Version | Supported | | ------- | ------------------ | | Latest | :white_check_mark: | -| Previous| :white_check_mark: | | Older | :x: | We recommend always using the latest version to ensure you have the most recent security updates. @@ -20,7 +19,9 @@ If you discover a security vulnerability in BuildMark, please help us by reporti **Do not** report security vulnerabilities through public GitHub issues. -Instead, please report security issues by creating a private security advisory on GitHub. +**Preferred method**: Use [GitHub's private vulnerability reporting][github-security-advisories] to +submit a security advisory directly in the repository. This keeps the report private until a fix +is available. ### What to Include @@ -45,6 +46,26 @@ When reporting a vulnerability, please include: - Credit will be given to reporters unless they prefer to remain anonymous - Public disclosure will occur after a fix is available +## Security Disclosure Policy + +We follow a coordinated disclosure process: + +1. **Report**: Submit vulnerability report via GitHub Security Advisories +2. **Acknowledgment**: We acknowledge receipt within 48 hours +3. **Assessment**: We assess the vulnerability and determine severity within 7 days +4. **Resolution**: We develop and test a fix, then release a patch version +5. **Disclosure**: We publicly disclose the vulnerability after the fix is released + +## Third-Party Dependencies + +BuildMark uses third-party NuGet packages. To check for vulnerable dependencies: + +```bash +dotnet list package --vulnerable +``` + +We use Dependabot to automatically monitor and update dependencies with known vulnerabilities. + ## Security Best Practices When using BuildMark: @@ -82,3 +103,13 @@ Security updates will be: For security concerns or questions about this policy, please use GitHub's security advisory feature or contact the project maintainers through the repository. + +## Additional Resources + +- [OWASP Top Ten][owasp-top-ten] +- [.NET Security Best Practices][dotnet-security] +- [GitHub Security Advisories][github-security-advisories] + +[github-security-advisories]: https://github.com/demaconsulting/BuildMark/security/advisories/new +[owasp-top-ten]: https://owasp.org/www-project-top-ten/ +[dotnet-security]: https://learn.microsoft.com/en-us/dotnet/standard/security/ diff --git a/build.bat b/build.bat index 9f2e4ef..f25b0ac 100644 --- a/build.bat +++ b/build.bat @@ -1,16 +1,17 @@ @echo off +REM Build and test BuildMark (Windows) setlocal echo Building BuildMark... dotnet build --configuration Release -if errorlevel 1 exit /b 1 +if %errorlevel% neq 0 exit /b %errorlevel% echo Running unit tests... dotnet test --configuration Release -if errorlevel 1 exit /b 1 +if %errorlevel% neq 0 exit /b %errorlevel% echo Running self-validation... dotnet run --project src/DemaConsulting.BuildMark --configuration Release --framework net10.0 --no-build -- --validate -if errorlevel 1 exit /b 1 +if %errorlevel% neq 0 exit /b %errorlevel% echo Build, tests, and validation completed successfully! diff --git a/build.sh b/build.sh index e296d37..1355a1f 100755 --- a/build.sh +++ b/build.sh @@ -1,5 +1,6 @@ -#!/bin/bash -set -e +#!/usr/bin/env bash +# Build and test BuildMark +set -e # Exit on error echo "🔧 Building BuildMark..." dotnet build --configuration Release diff --git a/docs/guide/guide.md b/docs/guide/guide.md index a68ed27..bb9fc85 100644 --- a/docs/guide/guide.md +++ b/docs/guide/guide.md @@ -184,27 +184,63 @@ buildmark --build-version v1.2.3 --report build-notes.md --include-known-issues ## Self-Validation -### `--validate` +Self-validation produces a report demonstrating that BuildMark is functioning correctly. This is useful in +regulated industries where tool validation evidence is required. -Run built-in self-validation tests. These tests verify BuildMark functionality without requiring access to a real -Git repository or GitHub. +### Running Validation + +To perform self-validation: ```bash buildmark --validate ``` -### `--results ` - -Write validation results to a file. Supports TRX (`.trx`) and JUnit XML (`.xml`) formats. Requires `--validate`. +To save validation results to a file: ```bash -# TRX format -buildmark --validate --results validation-results.trx +buildmark --validate --results results.trx +``` + +The results file format is determined by the file extension: `.trx` for TRX (MSTest) format, +or `.xml` for JUnit format. + +### Validation Report + +The validation report contains the tool version, machine name, operating system version, +.NET runtime version, timestamp, and test results. + +Example validation report: + +```text +# DEMA Consulting BuildMark Self-validation + +| Information | Value | +| :------------------ | :------------------------------------------------- | +| BuildMark Version | 1.0.0 | +| Machine Name | BUILD-SERVER | +| OS Version | Ubuntu 22.04.3 LTS | +| DotNet Runtime | .NET 10.0.0 | +| Time Stamp | 2024-01-15 10:30:00 UTC | -# JUnit XML format -buildmark --validate --results validation-results.xml +✓ BuildMark_MarkdownReportGeneration - Passed +✓ BuildMark_GitIntegration - Passed +✓ BuildMark_IssueTracking - Passed +✓ BuildMark_KnownIssuesReporting - Passed + +Total Tests: 4 +Passed: 4 +Failed: 0 ``` +### Validation Tests + +Each test proves specific functionality works correctly: + +- **`BuildMark_MarkdownReportGeneration`** - Markdown report is correctly generated from mock data. +- **`BuildMark_GitIntegration`** - Git repository connector reads version tags and commits. +- **`BuildMark_IssueTracking`** - GitHub issue and pull request tracking works correctly. +- **`BuildMark_KnownIssuesReporting`** - Known issues are correctly included when requested. + # Common Use Cases ## CI/CD Integration @@ -333,78 +369,6 @@ Provides a link to the full changelog on GitHub comparing the baseline and curre [View Full Changelog](https://github.com/owner/repo/compare/v1.2.0...v1.2.3) ``` -# Running Self-Validation - -BuildMark includes built-in self-validation tests to verify functionality without requiring access to a real -Git repository or GitHub. The validation uses mock data to test core features. - -## Running Validation - -```bash -buildmark --validate -``` - -## Validation Tests - -The self-validation suite includes the following tests that verify core functionality: - -| Test Name | Description | -| :-------- | :---------- | -| `BuildMark_MarkdownReportGeneration` | Verifies generating markdown build notes reports | -| `BuildMark_GitIntegration` | Verifies git integration for version and commit information | -| `BuildMark_IssueTracking` | Verifies issue tracking for changes and bugs | -| `BuildMark_KnownIssuesReporting` | Verifies known issues reporting functionality | - -These tests provide evidence of the tool's functionality and are particularly useful for: - -- Verifying the installation is working correctly on different platforms and .NET versions -- Running automated tests in CI/CD pipelines without requiring repository access -- Generating test evidence for compliance and traceability requirements -- Validating tool functionality before deployment - -**Note**: The test names with the `BuildMark_` prefix are designed for clear identification in test -result files (TRX/JUnit) when integrating with larger projects or test frameworks. - -## Validation Output - -Example output: - -```text -BuildMark version 1.0.0 -Copyright (c) DEMA Consulting - -# DEMA Consulting BuildMark Self-validation - -| Information | Value | -| :------------------ | :------------------------------------------------- | -| BuildMark Version | 1.0.0 | -| Machine Name | my-machine | -| OS Version | Ubuntu 24.04.3 LTS | -| DotNet Runtime | .NET 10.0.3 | -| Time Stamp | 2026-01-15 10:30:00 UTC | - -✓ Markdown Report Generation Test - PASSED -✓ Git Integration Test - PASSED -✓ Issue Tracking Test - PASSED -✓ Known Issues Reporting Test - PASSED - -Total Tests: 4 -Passed: 4 -Failed: 0 -``` - -## Saving Validation Results - -Save results in TRX or JUnit XML format for integration with test reporting tools: - -```bash -# TRX format (for Azure DevOps, Visual Studio) -buildmark --validate --results validation-results.trx - -# JUnit XML format (for Jenkins, GitLab CI) -buildmark --validate --results validation-results.xml -``` - # Version Selection Rules BuildMark automatically determines which previous version to use as the baseline when generating build notes. This diff --git a/lint.bat b/lint.bat index d85f8c7..722b6a4 100644 --- a/lint.bat +++ b/lint.bat @@ -1,16 +1,21 @@ @echo off +REM Lint BuildMark (Windows) setlocal -REM Run markdown linter +echo Checking code formatting... +dotnet format --verify-no-changes +if %errorlevel% neq 0 exit /b %errorlevel% + +echo Checking markdown... call npx markdownlint-cli2 "**/*.md" -if errorlevel 1 exit /b 1 +if %errorlevel% neq 0 exit /b %errorlevel% -REM Run spell checker +echo Checking spelling... call npx cspell "**/*.{md,cs}" -if errorlevel 1 exit /b 1 +if %errorlevel% neq 0 exit /b %errorlevel% -REM Run YAML linter +echo Checking YAML... call yamllint . -if errorlevel 1 exit /b 1 +if %errorlevel% neq 0 exit /b %errorlevel% -echo Linting completed successfully! +echo All linting passed! diff --git a/lint.sh b/lint.sh index a562889..d3f8752 100755 --- a/lint.sh +++ b/lint.sh @@ -1,11 +1,17 @@ -#!/bin/bash -set -e +#!/usr/bin/env bash +# Lint BuildMark +set -e # Exit on error -# Run markdown linter +echo "🎨 Checking code formatting..." +dotnet format --verify-no-changes + +echo "📝 Checking markdown..." npx markdownlint-cli2 "**/*.md" -# Run spell checker +echo "🔤 Checking spelling..." npx cspell "**/*.{md,cs}" -# Run YAML linter +echo "📋 Checking YAML..." yamllint . + +echo "✨ All linting passed!" diff --git a/package.json b/package.json index ccccfb1..9487fa5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "dependencies": { + "devDependencies": { "@mermaid-js/mermaid-cli": "11.12.0", "mermaid-filter": "1.4.7" } diff --git a/requirements.yaml b/requirements.yaml index 93c46dc..6a6f958 100644 --- a/requirements.yaml +++ b/requirements.yaml @@ -4,7 +4,7 @@ sections: sections: - title: Command-Line Interface requirements: - - id: CLI-001 + - id: BuildMark-Cmd-Cli title: The tool shall provide a command-line interface. justification: | A command-line interface is essential for BuildMark to integrate seamlessly into @@ -15,7 +15,7 @@ sections: - IntegrationTest_VersionFlag_OutputsVersion - IntegrationTest_HelpFlag_OutputsUsageInformation - - id: CLI-002 + - id: BuildMark-Cmd-Version title: The tool shall display version information when requested. justification: | Version information helps users identify which version of BuildMark they are running, @@ -24,7 +24,7 @@ sections: tests: - IntegrationTest_VersionFlag_OutputsVersion - - id: CLI-003 + - id: BuildMark-Cmd-Help title: The tool shall display help information when requested. justification: | Help information provides users with immediate access to usage instructions, available @@ -33,7 +33,7 @@ sections: tests: - IntegrationTest_HelpFlag_OutputsUsageInformation - - id: CLI-004 + - id: BuildMark-Cmd-Silent title: The tool shall support silent mode to suppress console output. justification: | Silent mode is essential for automated build environments where excessive console @@ -42,7 +42,7 @@ sections: tests: - IntegrationTest_SilentFlag_SuppressesOutput - - id: CLI-005 + - id: BuildMark-Cmd-Log title: The tool shall support writing output to a log file. justification: | Log file support enables persistent storage of BuildMark output for audit trails, @@ -51,7 +51,7 @@ sections: tests: - IntegrationTest_LogParameter_IsAccepted - - id: CLI-006 + - id: BuildMark-Cmd-BuildVersion title: The tool shall support specifying a build version. justification: | Specifying a build version allows users to override or supplement version information @@ -60,7 +60,7 @@ sections: tests: - IntegrationTest_BuildVersionParameter_IsAccepted - - id: CLI-007 + - id: BuildMark-Cmd-InvalidArgs title: The tool shall validate command-line arguments. justification: | Argument validation prevents misuse of the tool and provides clear error messages @@ -78,7 +78,7 @@ sections: - Context_Create_ResultsWithoutValue_ThrowsArgumentException - Context_Create_LogWithoutValue_ThrowsArgumentException - - id: CLI-008 + - id: BuildMark-Cmd-FilePaths title: The tool shall handle invalid file paths gracefully. justification: | Graceful handling of invalid file paths prevents cryptic error messages and ensures @@ -87,7 +87,7 @@ sections: tests: - Context_Create_InvalidLogFilePath_ThrowsInvalidOperationException - - id: CLI-009 + - id: BuildMark-Cmd-ExitCode title: The tool shall return appropriate exit codes. justification: | Standard exit codes enable build automation systems and scripts to detect success @@ -99,7 +99,7 @@ sections: - title: GitHub Integration requirements: - - id: GH-001 + - id: BuildMark-GH-BuildNotes title: The tool shall generate build notes from GitHub repositories. justification: | Generating build notes from GitHub repositories automates the documentation of @@ -110,7 +110,7 @@ sections: - BuildMark_GitIntegration - BuildMark_MarkdownReportGeneration - - id: GH-002 + - id: BuildMark-GH-IssueTracking title: The tool shall track issues and pull requests from GitHub. justification: | Tracking issues and pull requests provides traceability between code changes and @@ -119,7 +119,7 @@ sections: tests: - BuildMark_IssueTracking - - id: GH-003 + - id: BuildMark-GH-VersionTags title: The tool shall identify changes between version tags. justification: | Identifying changes between version tags enables differential release notes that @@ -130,7 +130,7 @@ sections: - title: Report Generation requirements: - - id: RPT-001 + - id: BuildMark-Rpt-Markdown title: The tool shall generate markdown reports. justification: | Markdown is a widely-adopted, human-readable format that works seamlessly with @@ -141,7 +141,7 @@ sections: - BuildMark_MarkdownReportGeneration - IntegrationTest_ReportParameter_IsAccepted - - id: RPT-002 + - id: BuildMark-Rpt-Depth title: The tool shall support configurable report depth. justification: | Configurable report depth allows BuildMark output to be embedded within existing @@ -151,7 +151,7 @@ sections: - IntegrationTest_ReportDepthParameter_IsAccepted - BuildInformation_ToMarkdown_RespectsCustomHeadingDepth - - id: RPT-003 + - id: BuildMark-Rpt-VersionInfo title: The tool shall report version information in build notes. justification: | Version information clearly identifies which release the build notes describe, @@ -160,7 +160,7 @@ sections: tests: - BuildMark_MarkdownReportGeneration - - id: RPT-004 + - id: BuildMark-Rpt-Changes title: The tool shall report changes in build notes. justification: | Reporting changes documents new features and enhancements introduced in each @@ -170,7 +170,7 @@ sections: - BuildMark_MarkdownReportGeneration - BuildInformation_ToMarkdown_DisplaysNAForEmptyChanges - - id: RPT-005 + - id: BuildMark-Rpt-BugFixes title: The tool shall report bug fixes in build notes. justification: | Documenting bug fixes informs users about resolved issues, demonstrates ongoing @@ -180,7 +180,7 @@ sections: - BuildMark_MarkdownReportGeneration - BuildInformation_ToMarkdown_DisplaysNAForEmptyBugs - - id: RPT-006 + - id: BuildMark-Rpt-KnownIssues title: The tool shall support including known issues in build notes. justification: | Disclosing known issues in release notes promotes transparency, helps users avoid @@ -189,7 +189,7 @@ sections: tests: - BuildMark_KnownIssuesReporting - - id: RPT-007 + - id: BuildMark-Rpt-VersionRange title: The tool shall support filtering build notes by version range. justification: | Version range filtering enables generation of cumulative release notes covering @@ -198,7 +198,7 @@ sections: tests: - BuildMark_MarkdownReportGeneration - - id: RPT-008 + - id: BuildMark-Rpt-Hyperlinks title: The tool shall include hyperlinks to issues and pull requests. justification: | Hyperlinks provide direct navigation to detailed information about changes, @@ -209,7 +209,7 @@ sections: - BuildInformation_ToMarkdown_IncludesIssueLinks - BuildInformation_ToMarkdown_IncludesFullChangelogWhenLinkPresent - - id: RPT-009 + - id: BuildMark-Rpt-Structure title: The tool shall format build notes with proper markdown structure. justification: | Proper markdown structure ensures reports render correctly across different @@ -224,7 +224,7 @@ sections: - title: Validation and Testing requirements: - - id: VAL-001 + - id: BuildMark-Val-SelfValidation title: The tool shall support self-validation mode. justification: | Self-validation mode allows users to validate the tool's functionality in their @@ -233,7 +233,7 @@ sections: tests: - IntegrationTest_ValidateFlag_RunsSelfValidation - - id: VAL-002 + - id: BuildMark-Val-ResultsFiles title: The tool shall write validation results to test result files. justification: | Writing validation results to files enables integration with testing frameworks, @@ -242,7 +242,7 @@ sections: tests: - IntegrationTest_ResultsParameter_IsAccepted - - id: VAL-003 + - id: BuildMark-Val-TrxFormat title: The tool shall support TRX format for test results. justification: | TRX format support enables integration with Microsoft test tooling and Visual @@ -251,7 +251,7 @@ sections: tests: - IntegrationTest_ResultsParameter_IsAccepted - - id: VAL-004 + - id: BuildMark-Val-JUnitFormat title: The tool shall support JUnit format for test results. justification: | JUnit format is a widely-supported standard across many CI/CD platforms and @@ -262,7 +262,7 @@ sections: - title: Platform Support requirements: - - id: PLT-001 + - id: BuildMark-Plt-Windows title: The tool shall run on Windows operating systems. justification: | Windows support is essential for .NET developers working in Windows-centric @@ -279,7 +279,7 @@ sections: - windows@BuildMark_IssueTracking - windows@BuildMark_KnownIssuesReporting - - id: PLT-002 + - id: BuildMark-Plt-Linux title: The tool shall run on Linux operating systems. justification: | Linux support is critical for modern DevOps practices and cloud-native development @@ -296,7 +296,7 @@ sections: - ubuntu@BuildMark_IssueTracking - ubuntu@BuildMark_KnownIssuesReporting - - id: PLT-003 + - id: BuildMark-Plt-Net8 title: The tool shall support .NET 8.0 runtime. justification: | .NET 8.0 is a Long-Term Support (LTS) release with support through November 2026. @@ -310,7 +310,7 @@ sections: - dotnet8.x@BuildMark_IssueTracking - dotnet8.x@BuildMark_KnownIssuesReporting - - id: PLT-004 + - id: BuildMark-Plt-Net9 title: The tool shall support .NET 9.0 runtime. justification: | .NET 9.0 is a Standard Term Support (STS) release with support through May 2026. @@ -324,7 +324,7 @@ sections: - dotnet9.x@BuildMark_IssueTracking - dotnet9.x@BuildMark_KnownIssuesReporting - - id: PLT-005 + - id: BuildMark-Plt-Net10 title: The tool shall support .NET 10.0 runtime. justification: | .NET 10.0 is the next Long-Term Support (LTS) release planned for November 2025. diff --git a/src/DemaConsulting.BuildMark/Context.cs b/src/DemaConsulting.BuildMark/Context.cs index e0dfb31..8501426 100644 --- a/src/DemaConsulting.BuildMark/Context.cs +++ b/src/DemaConsulting.BuildMark/Context.cs @@ -151,7 +151,9 @@ private void OpenLogFile(string logFile) { try { - _logWriter = new StreamWriter(logFile, append: false); + // Open with AutoFlush enabled so log entries are immediately written to disk + // even if the application terminates unexpectedly before Dispose is called + _logWriter = new StreamWriter(logFile, append: false) { AutoFlush = true }; } // Generic catch is justified here to wrap any file system exception with context. // Expected exceptions include IOException, UnauthorizedAccessException, ArgumentException, @@ -361,7 +363,7 @@ public void WriteError(string message) { var previousColor = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine(message); + Console.Error.WriteLine(message); Console.ForegroundColor = previousColor; } diff --git a/src/DemaConsulting.BuildMark/DemaConsulting.BuildMark.csproj b/src/DemaConsulting.BuildMark/DemaConsulting.BuildMark.csproj index b57360f..07fe8b5 100644 --- a/src/DemaConsulting.BuildMark/DemaConsulting.BuildMark.csproj +++ b/src/DemaConsulting.BuildMark/DemaConsulting.BuildMark.csproj @@ -46,19 +46,27 @@ Organization: $(Company) + - + + + + - + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -67,11 +75,6 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/src/DemaConsulting.BuildMark/Program.cs b/src/DemaConsulting.BuildMark/Program.cs index 2857eb6..897d08b 100644 --- a/src/DemaConsulting.BuildMark/Program.cs +++ b/src/DemaConsulting.BuildMark/Program.cs @@ -66,19 +66,19 @@ private static int Main(string[] args) catch (ArgumentException ex) { // Print expected argument exceptions and return error code - Console.WriteLine($"Error: {ex.Message}"); + Console.Error.WriteLine($"Error: {ex.Message}"); return 1; } catch (InvalidOperationException ex) { // Print expected operation exceptions and return error code - Console.WriteLine($"Error: {ex.Message}"); + Console.Error.WriteLine($"Error: {ex.Message}"); return 1; } catch (Exception ex) { // Print unexpected exceptions and re-throw to generate event logs - Console.WriteLine($"Unexpected error: {ex.Message}"); + Console.Error.WriteLine($"Unexpected error: {ex.Message}"); throw; } } diff --git a/src/DemaConsulting.BuildMark/Validation.cs b/src/DemaConsulting.BuildMark/Validation.cs index 544990f..0e8de39 100644 --- a/src/DemaConsulting.BuildMark/Validation.cs +++ b/src/DemaConsulting.BuildMark/Validation.cs @@ -111,7 +111,6 @@ private static void RunMarkdownReportGeneration( context, testResults, "BuildMark_MarkdownReportGeneration", - "Markdown Report Generation Test", mockFactory, "build-report.md", (logContent, reportContent) => @@ -148,7 +147,6 @@ private static void RunGitIntegration( context, testResults, "BuildMark_GitIntegration", - "Git Integration Test", mockFactory, null, (logContent, _) => @@ -179,7 +177,6 @@ private static void RunIssueTracking( context, testResults, "BuildMark_IssueTracking", - "Issue Tracking Test", mockFactory, null, (logContent, _) => @@ -209,7 +206,6 @@ private static void RunKnownIssuesReporting( context, testResults, "BuildMark_KnownIssuesReporting", - "Known Issues Reporting Test", mockFactory, "known-issues-report.md", (logContent, reportContent) => @@ -235,7 +231,6 @@ private static void RunKnownIssuesReporting( /// The context for output. /// The test results collection. /// The name of the test. - /// The display name for console output. /// The mock connector factory. /// Optional report file name to generate. /// Function to validate test results. Returns null on success or error message on failure. @@ -243,7 +238,6 @@ private static void RunValidationTest( Context context, DemaConsulting.TestResults.TestResults testResults, string testName, - string displayName, Func mockFactory, string? reportFileName, Func validator) @@ -300,26 +294,26 @@ private static void RunValidationTest( if (errorMessage == null) { test.Outcome = DemaConsulting.TestResults.TestOutcome.Passed; - context.WriteLine($"✓ {displayName} - PASSED"); + context.WriteLine($"✓ {testName} - Passed"); } else { test.Outcome = DemaConsulting.TestResults.TestOutcome.Failed; test.ErrorMessage = errorMessage; - context.WriteError($"✗ {displayName} - FAILED: {errorMessage}"); + context.WriteError($"✗ {testName} - Failed: {errorMessage}"); } } else { test.Outcome = DemaConsulting.TestResults.TestOutcome.Failed; test.ErrorMessage = $"Program exited with code {exitCode}"; - context.WriteError($"✗ {displayName} - FAILED: Exit code {exitCode}"); + context.WriteError($"✗ {testName} - Failed: Exit code {exitCode}"); } } // Generic catch is justified here to handle any exception during test execution catch (Exception ex) { - HandleTestException(test, context, displayName, ex); + HandleTestException(test, context, testName, ex); } FinalizeTestResult(test, startTime, testResults); @@ -412,7 +406,7 @@ private static void HandleTestException( { test.Outcome = DemaConsulting.TestResults.TestOutcome.Failed; test.ErrorMessage = $"Exception: {ex.Message}"; - context.WriteError($"✗ {displayName} - FAILED: {ex.Message}"); + context.WriteError($"✗ {displayName} - Failed: {ex.Message}"); } /// diff --git a/test/DemaConsulting.BuildMark.Tests/ContextTests.cs b/test/DemaConsulting.BuildMark.Tests/ContextTests.cs index 38118e5..94c72d6 100644 --- a/test/DemaConsulting.BuildMark.Tests/ContextTests.cs +++ b/test/DemaConsulting.BuildMark.Tests/ContextTests.cs @@ -616,23 +616,23 @@ public void Context_WriteError_NotSilent_WritesToConsole() // Create context without silent flag using var context = Context.Create([]); - // Capture console output + // Capture console error output using var output = new StringWriter(); - var originalOut = Console.Out; + var originalError = Console.Error; try { - Console.SetOut(output); + Console.SetError(output); // Write an error context.WriteError("Error message"); - // Verify message was written to console + // Verify message was written to error console Assert.AreEqual("Error message" + Environment.NewLine, output.ToString()); } finally { - // Restore console output - Console.SetOut(originalOut); + // Restore console error output + Console.SetError(originalError); } } diff --git a/test/DemaConsulting.BuildMark.Tests/DemaConsulting.BuildMark.Tests.csproj b/test/DemaConsulting.BuildMark.Tests/DemaConsulting.BuildMark.Tests.csproj index 09fe506..0352369 100644 --- a/test/DemaConsulting.BuildMark.Tests/DemaConsulting.BuildMark.Tests.csproj +++ b/test/DemaConsulting.BuildMark.Tests/DemaConsulting.BuildMark.Tests.csproj @@ -25,6 +25,10 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -37,6 +41,11 @@ + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/DemaConsulting.BuildMark.Tests/ValidationTests.cs b/test/DemaConsulting.BuildMark.Tests/ValidationTests.cs index 9429f70..36318da 100644 --- a/test/DemaConsulting.BuildMark.Tests/ValidationTests.cs +++ b/test/DemaConsulting.BuildMark.Tests/ValidationTests.cs @@ -153,26 +153,26 @@ public void Validation_Run_WithUnsupportedResultsFileExtension_ShowsError() var unsupportedFile = Path.Combine(tempDir, "results.json"); var args = new[] { "--validate", "--results", unsupportedFile }; - using var outputWriter = new StringWriter(); + using var errorWriter = new StringWriter(); + var originalError = Console.Error; try { - // Capture console output - Console.SetOut(outputWriter); + // Capture console error output + Console.SetError(errorWriter); // Act using var context = Context.Create(args, () => new MockRepoConnector()); Validation.Run(context); - // Assert - Verify error message in output (WriteError writes to Console.WriteLine) - var output = outputWriter.ToString(); + // Assert - Verify error message in error output (WriteError writes to Console.Error) + var output = errorWriter.ToString(); Assert.Contains("Unsupported results file format", output); } finally { - // Restore console output - var standardOutput = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = true }; - Console.SetOut(standardOutput); + // Restore console error output + Console.SetError(originalError); } } finally @@ -195,26 +195,26 @@ public void Validation_Run_WithInvalidResultsFilePath_ShowsError() var invalidPath = Path.Combine("/invalid_path_that_does_not_exist_12345678", "results.trx"); var args = new[] { "--validate", "--results", invalidPath }; - using var outputWriter = new StringWriter(); + using var errorWriter = new StringWriter(); + var originalError = Console.Error; try { - // Capture console output - Console.SetOut(outputWriter); + // Capture console error output + Console.SetError(errorWriter); // Act using var context = Context.Create(args, () => new MockRepoConnector()); Validation.Run(context); - // Assert - Verify error message in output (WriteError writes to Console.WriteLine) - var output = outputWriter.ToString(); + // Assert - Verify error message in error output (WriteError writes to Console.Error) + var output = errorWriter.ToString(); Assert.Contains("Failed to write results file", output); } finally { - // Restore console output - var standardOutput = new StreamWriter(Console.OpenStandardOutput()) { AutoFlush = true }; - Console.SetOut(standardOutput); + // Restore console error output + Console.SetError(originalError); } } }