Skip to content

Fspw 703#53

Merged
MichalFrends1 merged 5 commits intomainfrom
fspw-703
Feb 12, 2026
Merged

Fspw 703#53
MichalFrends1 merged 5 commits intomainfrom
fspw-703

Conversation

@MatteoDelOmbra
Copy link
Contributor

@MatteoDelOmbra MatteoDelOmbra commented Feb 4, 2026

Review Checklist

  • Task version updated (x.x.0)
  • CHANGELOG.md updated
  • Solution builds
  • Warnings resolved (if possible)
  • Typos resolved
  • Tests cover new code
  • Description how to run tests locally added to README.md (if needed)
  • All tests pass locally

Summary by CodeRabbit

  • New Features

    • Added a task to list object versions in Amazon S3 with prefix filtering, max-keys limit, and configurable error behavior.
  • Tests

    • Added unit and functional tests for listing, pagination, and error handling with environment-driven test setup.
  • Documentation

    • Added README and CHANGELOG entries and registered the new task in the top-level README.
  • Chores

    • Added CI workflows and simplified cross-platform .gitignore.

@coderabbitai
Copy link

coderabbitai bot commented Feb 4, 2026

Walkthrough

Adds a new Frends task Frends.AmazonS3.ListObjectVersions: implementation, DTOs, helpers, tests, CI/release workflows, project/solution files, metadata, changelog, and documentation to list S3 bucket object versions.

Changes

Cohort / File(s) Summary
Workflows
.github/workflows/ListObjectVersions_release.yml, .github/workflows/ListObjectVersions_test_on_main.yml, .github/workflows/ListObjectVersions_test_on_push.yml
Three new GitHub Actions workflows reusing central FrendsTasks workflows for release, main CI, and push/feature CI with parameters, env names, and secrets mapping.
Ignore / Root Docs
.gitignore, README.md
Reworked .gitignore to broader platform-agnostic rules and added task entry to root README.
Solution & Projects
Frends.AmazonS3.ListObjectVersions/*.sln, Frends.AmazonS3.ListObjectVersions/*.csproj, Frends.AmazonS3.ListObjectVersions/.../*.csproj
New solution and projects targeting .NET 8.0 with AWS SDK, analyzers, packaging metadata and included additional files.
Task Metadata & Migration
Frends.AmazonS3.ListObjectVersions/FrendsTaskMetadata.json, Frends.AmazonS3.ListObjectVersions/migration.json, Frends.AmazonS3.ListObjectVersions/CHANGELOG.md, Frends.AmazonS3.ListObjectVersions/README.md
Added task metadata, initial migration, changelog (v1.0.0), and task README.
Public Definitions / DTOs
Frends.AmazonS3.ListObjectVersions/Definitions/*.cs
BucketObjectVersions.cs, Connection.cs, Error.cs, Input.cs, Options.cs, Regions.cs, Result.cs
Introduced Input/Connection/Options/Result/Error DTOs, BucketObjectVersions DTO, and Region enum with XML docs and defaults.
Implementation
Frends.AmazonS3.ListObjectVersions/Frends.AmazonS3.ListObjectVersions.cs
New public static task method ListObjectVersions: validates credentials, selects region, creates S3 client, checks bucket versioning, delegates listing to handler, and centralizes error handling.
Helpers
Frends.AmazonS3.ListObjectVersions/Helpers/*.cs
AmazonS3Handler.cs, ErrorHandler.cs
AmazonS3Handler: region mapping, versioning check, paginated ListVersions mapping to DTOs. ErrorHandler: unified throw-or-return semantics.
Tests & Test infra
Frends.AmazonS3.ListObjectVersions/Frends.AmazonS3.ListObjectVersions.Tests/*
*.csproj, TestBase.cs, GlobalSuppressions.cs, .env.example, FunctionalTests.cs, ErrorHandlerTest.cs
New NUnit test project: TestBase loads .env, functional tests with S3 setup/teardown, unit tests for ErrorHandler, and GlobalSuppressions for analyzers.
Global suppressions
Frends.AmazonS3.ListObjectVersions/GlobalSuppressions.cs, Frends.AmazonS3.ListObjectVersions.Tests/GlobalSuppressions.cs
Assembly-level StyleCop suppressions added for both projects.

Sequence Diagram(s)

sequenceDiagram
  participant Caller as Client
  participant Task as AmazonS3.ListObjectVersions
  participant Handler as AmazonS3Handler
  participant AWSClient as AmazonS3Client
  participant S3 as S3 Service
  participant ErrorHandler as ErrorHandler

  Caller->>Task: Invoke ListObjectVersions(Input, Connection, Options)
  Task->>Handler: RegionSelection(connection.Region)
  Task->>AWSClient: Create client(credentials, region)
  Task->>Handler: CheckVersioningSetup(client, input)
  Handler->>AWSClient: GetBucketVersioningAsync(bucket)
  AWSClient->>S3: Request versioning status
  S3-->>AWSClient: Versioning status
  AWSClient-->>Handler: VersioningResponse
  Handler->>AWSClient: ListVersionsAsync(request) [paginated]
  AWSClient->>S3: ListObjectVersions request(s)
  S3-->>AWSClient: Versions response(s)
  AWSClient-->>Handler: VersionsResponse
  Handler-->>Task: Mapped Result (Objects)
  Task-->>Caller: Return Result
  alt exception occurs
    Task->>ErrorHandler: Handle(exception, options.ThrowErrorOnFailure, options.ErrorMessageOnFailure)
    ErrorHandler-->>Task: throws or returns Result(Success=false, Error)
    Task-->>Caller: throws or returns error result
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • MichalFrends1

Poem

🐇
I hopped through code to fetch each old key,
Versions like carrots lined up for me.
With helpers and tests I nibbled away,
Now S3's histories dance in bright array,
Hooray — a rabbit's tidy deploy fête!

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Title check ⚠️ Warning The title 'Fspw 703' is a reference to a ticket or issue identifier but does not describe what the pull request actually changes. Use a clear, descriptive title that explains the main change (e.g., 'Add ListObjectVersions task for Amazon S3' or 'Implement S3 ListObjectVersions operation')
Docstring Coverage ⚠️ Warning Docstring coverage is 5.26% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fspw-703

No actionable comments were generated in the recent review. 🎉


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 9

🤖 Fix all issues with AI agents
In @.github/workflows/ListObjectVersions_release.yml:
- Around line 8-16: The reusable workflow reference currently uses a mutable
branch ("uses: FrendsPlatform/FrendsTasks/.github/workflows/release.yml@main");
update the "uses" value to pin to an immutable commit SHA (e.g. replace "@main"
with "@<commit-sha>") so the build job named "build" always invokes the exact
release.yml commit; locate the "uses" entry in the job definition and substitute
the branch suffix with the repository commit SHA.

In @.github/workflows/ListObjectVersions_test_on_main.yml:
- Around line 13-25: The reusable workflow reference in the build job currently
uses an unstable ref
"FrendsPlatform/FrendsTasks/.github/workflows/linux_build_main.yml@main";
replace the "@main" ref with a pinned immutable commit SHA or a stable tag to
prevent CI behavior changes (update the value in the uses field for the build
job so it reads .../linux_build_main.yml@<COMMIT_SHA_OR_TAG>), and ensure the
chosen SHA/tag is committed/published in the FrendsPlatform/FrendsTasks repo
before pushing this change.

In `@Frends.AmazonS3.ListObjectVersions/CHANGELOG.md`:
- Around line 1-7: Update the CHANGELOG to follow Keep a Changelog by adding an
"## [Unreleased]" section above "## [1.0.0]" and move/split entries so that "###
Added" under Unreleased lists specific functional items (e.g., S3
ListObjectVersions task, versioning support, filtering options, authentication
details) rather than the vague "Initial implementation"; keep "## [1.0.0] -
2026-02-04" as the released snapshot and ensure any breaking changes would be
marked under "### Changed" or "### Removed" with upgrade notes; retain the "###
Added" heading name from the diff to locate where to place the specific feature
bullets.

In
`@Frends.AmazonS3.ListObjectVersions/Frends.AmazonS3.ListObjectVersions.Tests/.env.example`:
- Around line 2-3: The .env.example currently uses quoted values which become
part of the variable value; update ACCESS_KEY and SECRET_ACCESS_KEY to remove
surrounding quotes so the values are plain (e.g., ACCESS_KEY=example and
SECRET_ACCESS_KEY=example2) ensuring clients copying the file get correct
credentials; edit the lines containing the ACCESS_KEY and SECRET_ACCESS_KEY
entries to remove the quote characters.

In
`@Frends.AmazonS3.ListObjectVersions/Frends.AmazonS3.ListObjectVersions.Tests/FunctionalTests.cs`:
- Around line 60-79: The current cleanup uses s3Client.ListObjectsV2Async which
only returns current live objects and misses versioned objects and delete
markers; replace the logic that calls ListObjectsV2Async and builds
DeleteObjectsRequest with a loop using s3Client.ListVersionsAsync
(ListVersionsRequest) to enumerate all object versions and delete markers
(handle pagination via IsTruncated/NextKeyMarker/NextVersionIdMarker), build
DeleteObjectsRequest.Objects from each Version/DeleteMarker by including both
Key and VersionId (KeyVersion.VersionId) and call s3Client.DeleteObjectsAsync
for each batch until no versions remain so DeleteBucketAsync can succeed.

In
`@Frends.AmazonS3.ListObjectVersions/Frends.AmazonS3.ListObjectVersions/Definitions/BucketObjectVersions.cs`:
- Around line 20-25: Rename the BucketObjectVersions property from Etag to ETag
to follow abbreviation casing and update all usages; specifically change the
property in class BucketObjectVersions to ETag and update the mapping in
AmazonS3Handler where it assigns the value (look for the assignment that sets
Etag) to instead set ETag. Ensure any serialization attributes, XML/JSON
mappings, tests, and other references are updated to the new property name to
keep behavior unchanged.

In
`@Frends.AmazonS3.ListObjectVersions/Frends.AmazonS3.ListObjectVersions/Definitions/Result.cs`:
- Line 19: The XML doc comment above the Result class contains a typo in the
example tag: remove the extra leading slashes so the tag is a proper XML doc
comment (change "/// /// <example>[{}, {}]</example>" to "/// <example>[{},
{}]</example>") in the Result class's documentation to correct the comment
formatting.

In
`@Frends.AmazonS3.ListObjectVersions/Frends.AmazonS3.ListObjectVersions/Frends.AmazonS3.ListObjectVersions.cs`:
- Line 24: Update the XML <returns> documentation to match the actual Result
type used by the operation: replace the incorrect "string Output" with the
correct property signature (List<BucketObjectVersions> Objects) and include the
Success and Error shapes to reflect the Result class; locate the documentation
on the method that returns the Result class (e.g., the ListObjectVersions API
method and the Result type definition) and update the comment to read something
like: object { bool Success, List<BucketObjectVersions> Objects, object Error {
string Message, Exception AdditionalInfo } }.

In
`@Frends.AmazonS3.ListObjectVersions/Frends.AmazonS3.ListObjectVersions/Helpers/AmazonS3Handler.cs`:
- Around line 14-39: The ListObjectVersions method currently fetches only the
first page; change it to fully paginate like ListObjects by looping while
response.IsTruncated is true: create a ListVersionsRequest once (set BucketName,
MaxKeys, Prefix) and in a do/while or while loop call
client.ListVersionsAsync(request, cancellationToken), add response.Versions to
result.Objects each iteration (same mapping to BucketObjectVersions), then set
request.KeyMarker = response.NextKeyMarker and request.VersionIdMarker =
response.NextVersionIdMarker before the next call; after the loop set
result.ResponseTruncated = false (or reflect final response.IsTruncated) and
return the accumulated result, keeping ConfigureAwait(false) on async calls.
🧹 Nitpick comments (8)
Frends.AmazonS3.ListObjectVersions/Frends.AmazonS3.ListObjectVersions/GlobalSuppressions.cs (1)

3-10: Prefer narrowing suppressions to the smallest possible scope.

Assembly-level suppressions apply to the whole project and can hide unrelated issues. If feasible, target specific namespaces/types/members via Target/Scope to keep StyleCop coverage meaningful.

Frends.AmazonS3.ListObjectVersions/Frends.AmazonS3.ListObjectVersions/Helpers/AmazonS3Handler.cs (1)

55-56: Use a more specific exception type and consider null safety.

Using generic Exception makes it harder for callers to distinguish this error from other failures. Consider InvalidOperationException which better conveys "operation cannot proceed in this state."

Additionally, while uncommon, VersioningConfig could theoretically be null for buckets that have never had versioning configured.

♻️ Proposed fix
-        if (response.VersioningConfig.Status != VersionStatus.Enabled)
-            throw new Exception("Versioning is not enabled on bucket.");
+        if (response.VersioningConfig?.Status != VersionStatus.Enabled)
+            throw new InvalidOperationException("Versioning is not enabled on bucket.");
Frends.AmazonS3.ListObjectVersions/Frends.AmazonS3.ListObjectVersions.Tests/Frends.AmazonS3.ListObjectVersions.Tests.csproj (1)

16-23: Consider pinning package versions for reproducible builds.

Using wildcard versions (6.*, 18.*, 4.*) can lead to non-reproducible builds if a breaking change is introduced in a newer minor/patch version. Consider pinning to specific versions for more predictable CI behavior.

Frends.AmazonS3.ListObjectVersions/Frends.AmazonS3.ListObjectVersions.Tests/TestBase.cs (1)

9-14: Consider adding null validation for environment variables.

If the environment variables ACCESS_KEY or SECRET_ACCESS_KEY are not set, the tests will fail with potentially confusing error messages later. Adding validation in the constructor could provide clearer feedback.

💡 Suggested validation
 protected TestBase()
 {
     DotEnv.Load();
     AccessKey = Environment.GetEnvironmentVariable("ACCESS_KEY");
     SecretAccessKey = Environment.GetEnvironmentVariable("SECRET_ACCESS_KEY");
+
+    if (string.IsNullOrEmpty(AccessKey) || string.IsNullOrEmpty(SecretAccessKey))
+    {
+        throw new InvalidOperationException(
+            "AWS credentials not found. Ensure ACCESS_KEY and SECRET_ACCESS_KEY are set in the .env file.");
+    }
 }
Frends.AmazonS3.ListObjectVersions/Frends.AmazonS3.ListObjectVersions.Tests/ErrorHandlerTest.cs (2)

14-19: Redundant null check after Assert.ThrowsAsync.

When Assert.ThrowsAsync<Exception>() succeeds, it guarantees ex is not null. The assertion on Line 18 is redundant and can be removed for cleaner test code.

🧹 Suggested cleanup
 [Test]
 public void Should_Throw_Error_When_ThrowErrorOnFailure_Is_True()
 {
     var ex = Assert.ThrowsAsync<Exception>(() =>
         AmazonS3.ListObjectVersions(DefaultInput(), DefaultConnection(), DefaultOptions(), CancellationToken.None));
-    Assert.That(ex, Is.Not.Null);
+    Assert.That(ex.Message, Is.Not.Empty);
 }

31-40: Same redundant null check; also consider asserting the custom message more precisely.

Line 38's null check is redundant. Additionally, the test could verify the exact message match rather than just containing the substring.

🧹 Suggested cleanup
 [Test]
 public void Should_Use_Custom_ErrorMessageOnFailure()
 {
     var options = DefaultOptions();
     options.ErrorMessageOnFailure = CustomErrorMessage;
     var ex = Assert.ThrowsAsync<Exception>(() =>
         AmazonS3.ListObjectVersions(DefaultInput(), DefaultConnection(), options, CancellationToken.None));
-    Assert.That(ex, Is.Not.Null);
     Assert.That(ex.Message, Contains.Substring(CustomErrorMessage));
 }
Frends.AmazonS3.ListObjectVersions/Frends.AmazonS3.ListObjectVersions.Tests/FunctionalTests.cs (2)

40-50: Arbitrary Task.Delay calls may cause test flakiness.

Fixed delays (e.g., Task.Delay(1000)) can be unreliable in CI environments. Consider using polling/retry logic or AWS SDK waiters for eventual consistency scenarios.


134-149: Consider asserting ResponseTruncated flag when testing MaxKeys.

When MaxKeys limits results, the ResponseTruncated flag should be true. Adding this assertion would strengthen the test.

💡 Suggested enhancement
     Assert.That(result.Success, Is.True);
     Assert.That(result.Objects, Is.Not.Null);
     Assert.That(result.Objects.Count, Is.EqualTo(2));
     Assert.That(result.Error, Is.Null);
+    Assert.That(result.ResponseTruncated, Is.True);
 }

@MichalFrends1 MichalFrends1 merged commit 5d41057 into main Feb 12, 2026
5 checks passed
@MichalFrends1 MichalFrends1 deleted the fspw-703 branch February 12, 2026 10:14
@coderabbitai coderabbitai bot mentioned this pull request Feb 23, 2026
8 tasks
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.

2 participants