Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ECO-4980] Add a script to show spec coverage #93

Merged
merged 1 commit into from
Oct 31, 2024

Conversation

lawrence-forooghian
Copy link
Collaborator

@lawrence-forooghian lawrence-forooghian commented Oct 29, 2024

This generates a report, using our @spec etc tags, of which spec points we've implemented. This will help us to know what we still need to implement.

Resolves #46.

Summary by CodeRabbit

  • New Features

    • Introduced a new spec-coverage job to the GitHub Actions workflow for enhanced testing coverage analysis.
    • Added a SpecCoverage command in the BuildTool for reporting specification point implementations.
  • Documentation

    • Updated CONTRIBUTING.md to clarify testing guidelines and introduce new documentation standards for test-related APIs and spec points.
  • Chores

    • Added a new dependency, Table, to the project for improved functionality.

Copy link

coderabbitai bot commented Oct 29, 2024

Warning

Rate limit exceeded

@lawrence-forooghian has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 8 minutes and 2 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 4079c69 and 59cdb3b.

Walkthrough

The pull request introduces a new job named spec-coverage in the GitHub Actions workflow, which runs on macOS and executes a command to generate a specification coverage report. The all-checks-completed job is updated to depend on this new job. Additionally, a new dependency named table is added to the project, and enhancements are made to the CONTRIBUTING.md file regarding testing guidelines. The BuildTool is also updated to include a new command for analyzing spec coverage, along with necessary data structures and error handling.

Changes

File Change Summary
.github/workflows/check.yaml Added new job spec-coverage and updated all-checks-completed to depend on it.
AblyChat.xcworkspace/xcshareddata/swiftpm/Package.resolved Updated originHash and added new dependency table from https://github.com/JanGorman/Table.git.
Package.resolved Updated originHash and added new dependency table from https://github.com/JanGorman/Table.git.
Package.swift Added new package dependency for Table and updated BuildTool target dependencies.
Sources/BuildTool/BuildTool.swift Introduced SpecCoverage command with various structs and methods for handling spec coverage.
CONTRIBUTING.md Expanded guidelines on exposing test-only APIs, tagging tests, and generating coverage reports.

Assessment against linked issues

Objective Addressed Explanation
Write a script to show feature spec coverage (#46, ECO-4980)

Possibly related PRs

  • [ECO-4939] Require Xcode 16 or later #58: The changes in this PR also involve the .github/workflows/check.yaml file, specifically adding a job that sets up Xcode version 16, which is directly related to the new spec-coverage job introduced in the main PR.
  • Use main branch of ably-cocoa #81: This PR modifies the Package.resolved file, which is relevant as the main PR's spec-coverage job may depend on the correct resolution of package dependencies, including those related to the ably-cocoa library.

Suggested reviewers

  • umair-ably
  • maratal

Poem

🐇 In the garden where specs grow,
A coverage report now flows,
With tools to measure, test, and see,
Our code shines bright, as bright can be!
Hopping through changes, we celebrate,
For every spec point, we elevate! 🌼


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@lawrence-forooghian lawrence-forooghian force-pushed the 46-spec-coverage branch 3 times, most recently from 5836600 to 6e5faa3 Compare October 30, 2024 20:27
@lawrence-forooghian lawrence-forooghian changed the title [ECO-4980, WIP] Generate information about spec point coverage [ECO-4980, WIP] Add a script to show spec coverage Oct 30, 2024
@lawrence-forooghian lawrence-forooghian changed the title [ECO-4980, WIP] Add a script to show spec coverage [ECO-4980] Add a script to show spec coverage Oct 30, 2024
@lawrence-forooghian lawrence-forooghian marked this pull request as ready for review October 30, 2024 20:28
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: 8

🧹 Outside diff range and nitpick comments (4)
.github/workflows/check.yaml (1)

41-52: Consider enhancing the spec-coverage job configuration.

The basic job structure is correct, but consider these improvements for better reliability and visibility:

  1. Add timeout configuration to prevent hanging builds
  2. Implement caching similar to the lint job
  3. Upload the coverage report as an artifact for later reference

Here's a suggested enhancement:

 spec-coverage:
   runs-on: macos-latest
+  timeout-minutes: 10
   steps:
     - uses: actions/checkout@v4

     # This step can be removed once the runners' default version of Xcode is 16 or above
     - uses: maxim-lobanov/setup-xcode@v1
       with:
         xcode-version: 16

     - name: Spec coverage
       run: swift run BuildTool spec-coverage
+      
+    - name: Upload coverage report
+      uses: actions/upload-artifact@v4
+      with:
+        name: spec-coverage-report
+        path: spec-coverage-report.txt
+        if-no-files-found: error
CONTRIBUTING.md (2)

88-88: Consider enhancing the spec coverage report documentation.

While the command is clearly documented, consider adding:

  1. An example of the report output format
  2. The location where the report is generated
  3. Whether the strict comment format requirement (// with single spaces) could be made more flexible in future versions

Line range hint 65-87: LGTM! Consider clarifying tag selection guidance.

The tag documentation is comprehensive and well-structured. To make it even better, consider adding guidance on when to use @specPartial vs @specOneOf. For example:

  • Use @specOneOf when you have a planned set of test cases that together will provide full coverage
  • Use @specPartial when full coverage isn't achievable yet due to implementation limitations
Sources/BuildTool/BuildTool.swift (1)

273-277: Simplify optional binding with standard syntax

The use of the if let expression in this context may reduce readability. Consider using standard optional binding for clarity.

Simplify the code:

- let comment: String? = if let capture = match.output.5 {
-     String(capture)
- } else {
-     nil
- }
+ let comment = match.output.5.map { String($0) }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 21956dc and 6e5faa3.

📒 Files selected for processing (6)
  • .github/workflows/check.yaml (2 hunks)
  • AblyChat.xcworkspace/xcshareddata/swiftpm/Package.resolved (2 hunks)
  • CONTRIBUTING.md (1 hunks)
  • Package.resolved (2 hunks)
  • Package.swift (2 hunks)
  • Sources/BuildTool/BuildTool.swift (3 hunks)
🔇 Additional comments (9)
AblyChat.xcworkspace/xcshareddata/swiftpm/Package.resolved (2)

2-2: LGTM!

The originHash update is an expected change generated by Swift Package Manager.


58-65: Verify the table dependency details.

The Table package (v1.1.1) has been added for spec coverage reporting. Let's verify some important details about this dependency.

Package.resolved (1)

2-2: LGTM!

The originHash update is expected due to dependency changes.

Package.swift (2)

74-77: LGTM! Dependency correctly configured.

The Table product dependency is properly added to the BuildTool target, maintaining consistent formatting with other dependencies.


34-37: LGTM! Verify the package stability.

The Table package is a good choice for formatting CLI output. The version constraint is reasonable and allows for compatible updates.

Let's verify the package's maintenance status and compatibility:

✅ Verification successful

Package dependency verified and approved

The Table package shows healthy maintenance with recent updates (last updated: Jan 29, 2024) and is compatible with Swift toolchain. The package:

  • Is actively maintained
  • Has Swift as primary language
  • Matches the project's Swift tools version requirements (6.0)
  • Has a focused purpose ("CLI tables in Swift")
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check the Table package's recent activity and Swift version compatibility

# Test: Check if the package has recent commits and Swift version compatibility
gh repo view JanGorman/Table --json updatedAt,languages,description

# Test: Look for Swift version specifications in the package
rg -i "swift-tools-version" $(fd -t f "Package.swift" --exec dirname {})

Length of output: 913

.github/workflows/check.yaml (2)

132-132: LGTM!

The spec-coverage job is correctly integrated into the all-checks-completed dependencies, maintaining the workflow's gate-keeping functionality.


41-52: Verify job dependencies for spec-coverage.

Consider whether the spec-coverage job should run after successful SPM checks to ensure the codebase builds correctly before analyzing spec coverage.

Consider adding the following dependency:

 spec-coverage:
   runs-on: macos-latest
+  needs: check-spm
   steps:
CONTRIBUTING.md (1)

Line range hint 90-102: LGTM! Well-documented spec untested tag.

The @specUntested tag documentation is excellent:

  • Clear format requirements
  • Emphasis on sparing usage
  • Requirement for explanation
  • Good example demonstrating proper usage

This will help track and justify gaps in test coverage, which is valuable for maintaining transparency about test coverage status.

Sources/BuildTool/BuildTool.swift (1)

617-620: 🛠️ Refactor suggestion

Use Data(contentsOf:) instead of URLSession for local file access

Using URLSession.shared.data(from:) to read local files is unconventional and may introduce unnecessary overhead.

Apply this diff to read the file directly:

- let (data, _) = try await URLSession.shared.data(from: .init(filePath: path))
+ let data = try Data(contentsOf: URL(fileURLWithPath: path))

Likely invalid or redundant comment.

Package.resolved Show resolved Hide resolved
Sources/BuildTool/BuildTool.swift Show resolved Hide resolved
Sources/BuildTool/BuildTool.swift Show resolved Hide resolved
Sources/BuildTool/BuildTool.swift Show resolved Hide resolved
Sources/BuildTool/BuildTool.swift Show resolved Hide resolved
Sources/BuildTool/BuildTool.swift Show resolved Hide resolved
Sources/BuildTool/BuildTool.swift Show resolved Hide resolved
Sources/BuildTool/BuildTool.swift Show resolved Hide resolved
Copy link
Collaborator

@maratal maratal left a comment

Choose a reason for hiding this comment

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

I was expecting a test that will show how it works, but the code itself looks legit. Left one minor question.

Sources/BuildTool/BuildTool.swift Outdated Show resolved Hide resolved
@lawrence-forooghian
Copy link
Collaborator Author

I was expecting a test that will show how it works

What do you mean by "a test"?

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: 3

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 6e5faa3 and ee9be6f.

📒 Files selected for processing (6)
  • .github/workflows/check.yaml (2 hunks)
  • AblyChat.xcworkspace/xcshareddata/swiftpm/Package.resolved (2 hunks)
  • CONTRIBUTING.md (1 hunks)
  • Package.resolved (2 hunks)
  • Package.swift (2 hunks)
  • Sources/BuildTool/BuildTool.swift (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • .github/workflows/check.yaml
  • AblyChat.xcworkspace/xcshareddata/swiftpm/Package.resolved
  • CONTRIBUTING.md
  • Package.swift
🧰 Additional context used
📓 Learnings (1)
Sources/BuildTool/BuildTool.swift (5)
Learnt from: lawrence-forooghian
PR: ably-labs/ably-chat-swift#93
File: Sources/BuildTool/BuildTool.swift:232-233
Timestamp: 2024-10-31T12:09:46.733Z
Learning: In `Sources/BuildTool/BuildTool.swift`, when using `Regex.firstMatch(in:)` without a throwing transformation, it's acceptable to use `try!` as it won't throw an error.
Learnt from: lawrence-forooghian
PR: ably-labs/ably-chat-swift#93
File: Sources/BuildTool/BuildTool.swift:438-439
Timestamp: 2024-10-31T12:09:03.256Z
Learning: In `Sources/BuildTool/BuildTool.swift`, it's acceptable to use `try!` when calling `Table(data:).table()` because the only possible errors are programmer errors, making explicit error handling unnecessary.
Learnt from: lawrence-forooghian
PR: ably-labs/ably-chat-swift#93
File: Sources/BuildTool/BuildTool.swift:529-530
Timestamp: 2024-10-31T12:08:23.040Z
Learning: In Swift code, when encountering programmer errors, it's acceptable to use `preconditionFailure` instead of throwing an error.
Learnt from: lawrence-forooghian
PR: ably-labs/ably-chat-swift#93
File: Sources/BuildTool/BuildTool.swift:295-296
Timestamp: 2024-10-31T12:09:18.088Z
Learning: In this codebase, programmer errors are not handled by throwing `Error`s. Instead, `preconditionFailure` or similar methods are used.
Learnt from: lawrence-forooghian
PR: ably-labs/ably-chat-swift#93
File: Sources/BuildTool/BuildTool.swift:551-552
Timestamp: 2024-10-31T12:08:14.757Z
Learning: The codebase uses a throwing equivalent of `String(data:encoding:)`, so optional unwrapping suggestions are not needed in such cases.
🔇 Additional comments (3)
Package.resolved (2)

58-65: LGTM: Table dependency addition looks good.

The dependency is properly configured with pinned version 1.1.1. While the package is older, it appears to meet the current needs for formatting spec coverage reports.


2-2: LGTM: Expected hash update.

The originHash update is a normal consequence of adding the new dependency.

Sources/BuildTool/BuildTool.swift (1)

202-625: Overall Implementation Looks Good

The SpecCoverage command is well-structured, and the implementation aligns with the objectives of generating a specification coverage report. The use of Swift language features, asynchronous programming, and error handling follows best practices.

Sources/BuildTool/BuildTool.swift Show resolved Hide resolved
Sources/BuildTool/BuildTool.swift Outdated Show resolved Hide resolved
Sources/BuildTool/BuildTool.swift Outdated Show resolved Hide resolved
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: 1

🧹 Outside diff range and nitpick comments (2)
Sources/BuildTool/BuildTool.swift (2)

250-298: Consider improving regex readability

The regex pattern for parsing conformance tags is quite complex. Consider breaking it down into named capture groups or adding detailed comments explaining each part of the pattern.

- let conformanceTagSourceLineRegex = /^\s+\/\/ @spec(OneOf|Partial|Untested)?(?:\((\d)?\/(\d)?\))? (.*?)(?: - (.*))?$/
+ // Matches conformance tags in the format: @spec[Type][(n/m)] ID [- comment]
+ let conformanceTagSourceLineRegex = /
+     ^\s+\/\/\s+    # Leading whitespace and comment
+     @spec          # Tag start
+     (OneOf|Partial|Untested)?  # Optional tag type
+     (?:\((\d)?\/(\d)?\))?      # Optional (n/m) for OneOf tags
+     \s+(.*?)                   # Spec point ID
+     (?: - (.*))?$             # Optional comment
+ /x

365-365: Consider safer dictionary access

The double force unwrap could be replaced with a more defensive approach.

- let specPoint = specPointsByID[specPointID]!.first!
+ guard let specPoints = specPointsByID[specPointID],
+       let specPoint = specPoints.first else {
+     preconditionFailure("Spec point \(specPointID) not found in dictionary")
+ }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ee9be6f and 4079c69.

📒 Files selected for processing (6)
  • .github/workflows/check.yaml (2 hunks)
  • AblyChat.xcworkspace/xcshareddata/swiftpm/Package.resolved (2 hunks)
  • CONTRIBUTING.md (1 hunks)
  • Package.resolved (2 hunks)
  • Package.swift (2 hunks)
  • Sources/BuildTool/BuildTool.swift (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • .github/workflows/check.yaml
  • AblyChat.xcworkspace/xcshareddata/swiftpm/Package.resolved
  • CONTRIBUTING.md
  • Package.resolved
  • Package.swift
🧰 Additional context used
📓 Learnings (1)
Sources/BuildTool/BuildTool.swift (5)
Learnt from: lawrence-forooghian
PR: ably-labs/ably-chat-swift#93
File: Sources/BuildTool/BuildTool.swift:232-233
Timestamp: 2024-10-31T12:09:46.733Z
Learning: In `Sources/BuildTool/BuildTool.swift`, when using `Regex.firstMatch(in:)` without a throwing transformation, it's acceptable to use `try!` as it won't throw an error.
Learnt from: lawrence-forooghian
PR: ably-labs/ably-chat-swift#93
File: Sources/BuildTool/BuildTool.swift:438-439
Timestamp: 2024-10-31T12:09:03.256Z
Learning: In `Sources/BuildTool/BuildTool.swift`, it's acceptable to use `try!` when calling `Table(data:).table()` because the only possible errors are programmer errors, making explicit error handling unnecessary.
Learnt from: lawrence-forooghian
PR: ably-labs/ably-chat-swift#93
File: Sources/BuildTool/BuildTool.swift:529-530
Timestamp: 2024-10-31T12:08:23.040Z
Learning: In Swift code, when encountering programmer errors, it's acceptable to use `preconditionFailure` instead of throwing an error.
Learnt from: lawrence-forooghian
PR: ably-labs/ably-chat-swift#93
File: Sources/BuildTool/BuildTool.swift:295-296
Timestamp: 2024-10-31T12:09:18.088Z
Learning: In this codebase, programmer errors are not handled by throwing `Error`s. Instead, `preconditionFailure` or similar methods are used.
Learnt from: lawrence-forooghian
PR: ably-labs/ably-chat-swift#93
File: Sources/BuildTool/BuildTool.swift:551-552
Timestamp: 2024-10-31T12:08:14.757Z
Learning: The codebase uses a throwing equivalent of `String(data:encoding:)`, so optional unwrapping suggestions are not needed in such cases.
🔇 Additional comments (6)
Sources/BuildTool/BuildTool.swift (6)

Line range hint 1-17: LGTM!

The SpecCoverage command is properly registered in the BuildTool configuration.


203-214: LGTM!

The command structure is well-defined with comprehensive error cases for different failure scenarios.


216-248: LGTM!

The SpecFile implementation correctly parses spec points from the file content. The use of try! with firstMatch is acceptable here as per the established practice.


523-541: LGTM with known issue

The GitHub API interaction is implemented correctly, though there's a known issue with rate limiting that's already being addressed.


543-626: LGTM!

The file loading and parsing implementation is robust and follows the codebase's practices for error handling and string initialization.


498-499: 🛠️ Refactor suggestion

Make branch name configurable

The branch name is currently hardcoded to "chat-lifecycle". Consider making it a command-line option with "chat-lifecycle" as the default value.

+ @Option(help: "The branch name to fetch the spec from", default: "chat-lifecycle")
+ var branchName: String
+
 mutating func run() async throws {
-    // TODO: https://github.com/ably-labs/ably-chat-swift/issues/97 - switch to use main at some point
-    let branchName = "chat-lifecycle"

Likely invalid or redundant comment.

Sources/BuildTool/BuildTool.swift Show resolved Hide resolved
This will help us figure out what we still need to implement.

Resolves #46.
@maratal
Copy link
Collaborator

maratal commented Oct 31, 2024

I was expecting a test that will show how it works

What do you mean by "a test"?

I mean shouldn't this tool also be covered by tests? Although I understand that this is probably a bit too much.

@lawrence-forooghian
Copy link
Collaborator Author

I mean shouldn't this tool also be covered by tests? Although I understand that this is probably a bit too much.

Oh, I see. I’m not really in the habit of writing tests for this sort of script.

@lawrence-forooghian lawrence-forooghian merged commit c485d38 into main Oct 31, 2024
12 checks passed
@lawrence-forooghian lawrence-forooghian deleted the 46-spec-coverage branch October 31, 2024 14:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

Write a script to show feature spec coverage
2 participants