Skip to content

feat: Add zip assertion block for validating zip archive entry existence#47

Merged
Malcolmnixon merged 3 commits into
mainfrom
copilot/add-zip-file-checking-rules
May 15, 2026
Merged

feat: Add zip assertion block for validating zip archive entry existence#47
Malcolmnixon merged 3 commits into
mainfrom
copilot/add-zip-file-checking-rules

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented May 12, 2026

Pull Request

Description

Adds a zip: assertion block enabling FileAssert to validate that zip archives (including .nupkg, .jar, etc.) contain expected entries, with optional min/max count constraints and glob pattern matching.

New block: zip:

files:
  - pattern: "output/package.zip"
    zip:
      entries:
        - pattern: 'lib/net8.0/MyLib.dll'
          min: 1
          max: 1
        - pattern: 'lib/**/*.dll'
          min: 1

Entry paths are normalized to forward slashes before matching; glob patterns are resolved via Microsoft.Extensions.FileSystemGlobbing (same mechanism as FileAssertFile). No new NuGet dependencies — uses System.IO.Compression from the BCL.

Changes

  • Modeling/FileAssertZipAssert.cs — new zip assert unit; opens zip via ZipFile.OpenRead, collects all entry names, applies Matcher per pattern, enforces min/max
  • Configuration/FileAssertData.cs — new FileAssertZipEntryData and FileAssertZipData DTOs
  • Modeling/FileAssertFile.cs — wires the zip: block into the per-file assertion pipeline
  • README.md — documents new zip: block with YAML examples and acceptance criteria table entries
  • Documentation — design, requirements (reqstream), and verification docs added under docs/; introduction.md and .reviewmark.yaml updated to include the new unit

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Code quality improvement

Related Issues

Pre-Submission Checklist

Before submitting this pull request, ensure you have completed the following:

Build and Test

  • Code builds successfully and all tests pass: pwsh ./build.ps1
  • Code produces zero warnings

Code Quality

  • New code has appropriate XML documentation comments
  • Static analyzer warnings have been addressed

Quality Checks

Please run the following checks before submitting:

  • All linters pass: pwsh ./lint.ps1

Testing

  • Added unit tests for new functionality
  • Updated existing tests if behavior changed
  • All tests follow the AAA (Arrange, Act, Assert) pattern
  • Test coverage is maintained or improved

Documentation

  • Updated README.md (if applicable)
  • Updated docs/ documentation (if applicable)
  • Added code examples for new features (if applicable)
  • Updated requirements.yaml (if applicable)

Additional Notes

The zip: block intentionally checks only entry existence. Recursive content inspection of zip entries (text/HTML/JSON/etc.) is explicitly deferred — it would require abstracting the file-system interface used by existing rules. A future enhancement could support content checks on matched entries via stream-based overloads on each assert type (all relevant OTS libraries support stream/byte-array loading), or a full virtual filesystem abstraction for nested zip-in-zip scenarios.

Copilot AI linked an issue May 12, 2026 that may be closed by this pull request
3 tasks
Copilot AI and others added 2 commits May 12, 2026 21:07
Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com>
…ME table alignment

Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com>
Copilot AI changed the title [WIP] Add zip contents checking rules using FileAssert feat: Add zip-contains rule for asserting zip archive entry existence May 12, 2026
Copilot AI requested a review from Malcolmnixon May 12, 2026 21:23
@Malcolmnixon
Copy link
Copy Markdown
Member

@copilot What are your thoughts on this, and do you think it will be easy (in the future) to run the other checks (e.g. PDF, Yaml, Json) on files in the zip - would it need a virtual filesystem interface that could point to the real filesystem or a zip archive?

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 15, 2026

@copilot What are your thoughts on this, and do you think it will be easy (in the future) to run the other checks (e.g. PDF, Yaml, Json) on files in the zip - would it need a virtual filesystem interf...

Good question. The current design would need some refactoring to support running content checks (PDF, YAML, JSON, etc.) on entries inside a zip. Here's the analysis:

Current bottleneck: Every assert type (FileAssertPdfAssert, FileAssertXmlAssert, etc.) has a Run(Context, string fileName) signature that opens the file by filesystem path. Zip entries don't have filesystem paths.

Three paths forward, in order of effort:

  1. Extract-to-temp (no refactoring): When zip entry content checks are configured, extract matched entries to a temp directory then invoke the existing Run(context, tempPath) on those paths. Works today without touching any existing classes, but is I/O-heavy and requires careful cleanup.

  2. Stream-based overloads (medium refactor): Add Run(Context, string entryName, Stream stream) overloads to each assert type. All the OTS libraries already support it — PdfPig has PdfDocument.Open(byte[]), HtmlAgilityPack has HtmlDocument.Load(Stream), XDocument/YamlDotNet/System.Text.Json all accept TextReader or Stream. This avoids temp files and touches each assert class once.

  3. Virtual filesystem abstraction (full refactor): Introduce an IFileSystem interface (e.g., Stream OpenRead(string path)) and thread it through FileAssertFile.Run and all assert Run() methods. A RealFileSystem wraps File.OpenRead(); a ZipFileSystem returns entry streams. This is the architecturally "correct" approach and also enables nested zip-in-zip checking, but it's a significant cross-cutting change.

My recommendation for a future issue: start with option 2 (stream overloads). The individual per-type changes are straightforward and isolated, it handles all the common content check types cleanly, and it doesn't require the full virtual filesystem abstraction unless nested zip checking (zip-within-zip) becomes a requirement.

@Malcolmnixon Malcolmnixon requested a review from Copilot May 15, 2026 22:05
@Malcolmnixon Malcolmnixon marked this pull request as ready for review May 15, 2026 22:05
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds first-class zip archive entry assertions to FileAssert’s per-file checks, enabling validation that an archive contains expected entries via glob patterns and optional min/max match counts.

Changes:

  • Introduces a new zip: assertion block (DTO + modeling unit) that opens a zip and matches entry names with Microsoft.Extensions.FileSystemGlobbing.
  • Wires the new zip assert into FileAssertFile execution and updates README acceptance criteria + examples.
  • Adds unit tests and ReqStream/design/verification documentation (including .reviewmark.yaml coverage).

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
test/DemaConsulting.FileAssert.Tests/Modeling/FileAssertZipAssertTests.cs New unit tests for zip entry matching, bounds checking, and invalid/missing zip error paths.
src/DemaConsulting.FileAssert/Modeling/FileAssertZipAssert.cs New zip-assert implementation: open zip, normalize entry names, glob match, enforce min/max.
src/DemaConsulting.FileAssert/Modeling/FileAssertFile.cs Integrates zip: block into file-level assertion creation and per-file execution pipeline.
src/DemaConsulting.FileAssert/Configuration/FileAssertData.cs Adds YAML DTOs for zip: configuration (FileAssertZipData, FileAssertZipEntryData).
requirements.yaml Includes the new ReqStream unit requirements file for the zip assert unit.
README.md Documents the zip: assertion block in examples and the acceptance-criteria reference table.
docs/verification/file-assert/modeling/file-assert-zip-assert.md Unit-level verification design and scenario coverage for FileAssertZipAssert.
docs/verification/file-assert/modeling.md Adds zip-assert test coverage references to modeling subsystem verification.
docs/verification/file-assert.md Adds system-level verification scenarios/coverage references for zip assertions.
docs/reqstream/file-assert/modeling/file-assert-zip-assert.yaml New unit requirements for zip assert creation, entry matching, and parse errors.
docs/reqstream/file-assert/modeling.yaml Links zip assert requirements into Modeling subsystem requirement tree.
docs/reqstream/file-assert.yaml Adds system requirement for zip archive assertions and links children/tests.
docs/design/introduction.md Adds FileAssertZipAssert to the design introduction unit inventory.
docs/design/file-assert/modeling/file-assert-zip-assert.md Design doc for the new zip assert unit (behavior, YAML shape, errors).
docs/design/file-assert/modeling.md Adds zip assert to modeling subsystem design overview and hierarchy.
docs/design/file-assert.md Updates system design flow to include zip assertion execution path.
.reviewmark.yaml Adds the required per-unit review-set entry for the new modeling unit.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md
@Malcolmnixon
Copy link
Copy Markdown
Member

@copilot apply changes based on the comments in this thread

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 15, 2026

@copilot apply changes based on the comments in this thread

Done. The code and all documentation were already using zip: correctly. The PR title and description have been updated to remove the zip-contains references and consistently use the correct zip: block name throughout.

Copilot AI changed the title feat: Add zip-contains rule for asserting zip archive entry existence feat: Add zip assertion block for validating zip archive entry existence May 15, 2026
@Malcolmnixon Malcolmnixon merged commit 36474de into main May 15, 2026
21 checks passed
@Malcolmnixon Malcolmnixon deleted the copilot/add-zip-file-checking-rules branch May 15, 2026 22:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Zip contents checking

3 participants