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

Add release helper #284

Merged
merged 39 commits into from
Sep 26, 2024
Merged

Add release helper #284

merged 39 commits into from
Sep 26, 2024

Conversation

paulgb
Copy link
Member

@paulgb paulgb commented Sep 19, 2024

This PR introduces a Rust program that helps with keeping versions in sync across our rust/python/JS codebases, both in the repo and in their respective public registries.

See releaser/README.md for instructions on usage. This replaces the notion checklist (note: the current checklist is only accessible to Jamsocket notion workspace members) we previously followed, as well as set-js-version.ts which was removed in #285.

Instructions are in the README.

The goal is to reduce the chances of human error and reduce the toil that comes from managing multiple packages across several registries.

Copy link

vercel bot commented Sep 19, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

3 Skipped Deployments
Name Status Preview Comments Updated (UTC)
y-sweet-debugger ⬜️ Ignored (Inspect) Visit Preview Sep 26, 2024 7:42pm
y-sweet-demos ⬜️ Ignored (Inspect) Visit Preview Sep 26, 2024 7:42pm
y-sweet-gendocs ⬜️ Ignored (Inspect) Visit Preview Sep 26, 2024 7:42pm

@paulgb paulgb mentioned this pull request Sep 19, 2024
paulgb added a commit that referenced this pull request Sep 19, 2024
Note: this was created with a WIP tool that keeps versions in check
across our rust/python/npm packages, which can be found in the
[paulgb/releaser](#284) branch.
@paulgb paulgb changed the title Releaser wip Add release helper Sep 20, 2024
@paulgb paulgb marked this pull request as ready for review September 20, 2024 15:34
Copy link
Contributor

coderabbitai bot commented Sep 20, 2024

Caution

Review failed

The pull request is closed.

Walkthrough

The pull request introduces a series of changes across multiple files in the repository, primarily focused on enhancing the release management process. A new Rust package, ysweet-releaser, has been established, complete with a Cargo.toml that outlines various essential dependencies. The README.md file now provides comprehensive instructions for developers on managing versioning and releases. A command-line tool has been implemented in main.rs, which facilitates the release process through argument parsing and modular design.

New modules for managing packages in Rust, Node.js, and Python have been added, along with functionality in check_binaries.rs to verify binary artifacts. The git.rs file wraps Git operations, while the .gitignore file has been updated to exclude the target directory. Additionally, the pyproject.toml has been modified to include new optional dependencies. These changes collectively improve the structure and functionality of the release management system.

Possibly related PRs

  • Add release helper #284: This PR is related because it also modifies the .github/workflows/release.yml file by adding a comment about updating the check_binaries.rs file when binaries are added or removed, which directly connects to the changes made in the main PR regarding comments in the same file.

Suggested reviewers

  • michaelsilver
  • rolyatmax
  • feliciachang

Poem

🐰 In the garden of code, changes bloom bright,
New tools for the bunnies, oh what a sight!
With versions to bump and packages to share,
We hop through the branches without a care.
Let’s dance in the fields where the binaries play,
For the Y-Sweet reliever is here to stay! 🌼✨


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.

Copy link
Contributor

@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: 32

Outside diff range and nitpick comments (8)
releaser/src/check_binaries.rs (1)

24-36: LGTM with a suggestion!

The check_binaries function is implemented correctly:

  • It takes a Version as input and returns a Result<bool>.
  • Converts the version to a string to construct the URLs.
  • Iterates over the hardcoded list of binary names.
  • Constructs the URL for each binary using the hardcoded URL prefix and version.
  • Calls the is_url_ok function to check if the URL returns a 200 status code.
  • Returns false if any binary is not found, which is the correct behavior.
  • Returns true only if all binaries are found.
  • Error handling is done using the Result type.

Consider adding a comment above the BINARIES_TO_CHECK and BINARY_URL_PREFIX constants mentioning that they need to be updated if the list of binaries or the URL format changes in the future. This will serve as a reminder for developers modifying this code.

releaser/src/util.rs (2)

5-17: LGTM!

The function logic is correct, and the implementation is accurate. Great job using the dialoguer crate to simplify the user input process.

Consider the following suggestions for further improvement:

  1. Return a Result instead of unwrapping the interact() call to handle potential errors gracefully.
  2. Take a reference to the vector instead of moving it to avoid unnecessary memory allocation.

56-67: LGTM!

The function logic is correct, and the implementation is accurate. It's a useful utility function for finding the root directory of the project.

Consider the following suggestions for further improvement:

  1. Return a Result instead of panicking to handle the case where the root directory is not found gracefully.
  2. Take an optional starting path as an argument to allow searching from a specific directory.
releaser/README.md (1)

16-18: Consider specifying languages for fenced code blocks.

To improve syntax highlighting and readability, consider specifying the language for the fenced code blocks. For example:

-```
+```bash
cargo run -- bump

- +bash
cargo run -- publish




Also applies to: 43-45

<details>
<summary>Tools</summary>

<details>
<summary>Markdownlint</summary><blockquote>

16-16: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</blockquote></details>

</details>

</blockquote></details>
<details>
<summary>releaser/src/package_manager/mod.rs (1)</summary><blockquote>

`81-103`: **Consider caching `PackageManager` instances to improve performance.**

Each method in `Package` creates a new `PackageManager` instance. If these instances are stateless, this may be acceptable. However, if they maintain state or if instantiation is resource-intensive, caching them within the `Package` struct can enhance efficiency.



You might modify the `Package` struct to include a `package_manager` field:

```diff
 pub struct Package {
     pub name: String,
     pub path: PathBuf,
     pub package_type: PackageType,
+    package_manager: Box<dyn PackageManager>,
 }

And initialize it accordingly, reducing the need to create a new instance with every method call.

releaser/src/package_manager/python/mod.rs (2)

71-71: Clarify the error message when updating dependencies

The error message "Python dependencies not supported" might be unclear. Consider rephrasing it to "Updating Python dependencies is not supported" to provide better context.

Apply this diff to update the error message:

-return Err(anyhow::anyhow!("Python dependencies not supported"));
+return Err(anyhow::anyhow!("Updating Python dependencies is not supported"));

21-26: Include HTTP status in error message when fetching published version

Adding the HTTP status code to the error message can provide more context about why the request failed.

Apply this diff to enhance the error message:

return Err(anyhow::anyhow!(
-    "Failed to get public version for package {}",
-    package
+    "Failed to get public version for package {}: HTTP {}",
+    package,
+    response.status()
));
releaser/src/package_manager/cargo.rs (1)

155-159: Avoid Deserializing Unused Fields to Optimize Performance

The fields newest_version and max_stable_version are marked with #[allow(unused)]. If these fields are not used, you can omit them from the struct to simplify the code and slightly improve deserialization performance.

Apply this diff to exclude unused fields:

 #[derive(Debug, Deserialize)]
 struct CratesCrate {
-    #[allow(unused)]
-    newest_version: Version,
     max_version: Version,
-    #[allow(unused)]
-    max_stable_version: Version,
 }
Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits

Files that changed from the base of the PR and between 95d1a91 and 97286c2.

Files ignored due to path filters (1)
  • releaser/Cargo.lock is excluded by !**/*.lock
Files selected for processing (16)
  • .github/workflows/release.yml (1 hunks)
  • python/pyproject.toml (1 hunks)
  • releaser/.gitignore (1 hunks)
  • releaser/Cargo.toml (1 hunks)
  • releaser/README.md (1 hunks)
  • releaser/src/check_binaries.rs (1 hunks)
  • releaser/src/git.rs (1 hunks)
  • releaser/src/main.rs (1 hunks)
  • releaser/src/package_manager/cargo.rs (1 hunks)
  • releaser/src/package_manager/mod.rs (1 hunks)
  • releaser/src/package_manager/node.rs (1 hunks)
  • releaser/src/package_manager/python/mod.rs (1 hunks)
  • releaser/src/package_manager/python/virtualenv.rs (1 hunks)
  • releaser/src/packages.rs (1 hunks)
  • releaser/src/releaser.rs (1 hunks)
  • releaser/src/util.rs (1 hunks)
Files skipped from review due to trivial changes (2)
  • .github/workflows/release.yml
  • releaser/.gitignore
Additional context used
Markdownlint
releaser/README.md

12-12: Expected: setext; Actual: atx
Heading style

(MD003, heading-style)


29-29: Expected: setext; Actual: atx
Heading style

(MD003, heading-style)


37-37: Expected: setext; Actual: atx
Heading style

(MD003, heading-style)


16-16: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


43-43: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

Additional comments not posted (26)
releaser/Cargo.toml (1)

1-18: LGTM!

The Cargo.toml file is well-structured and includes all the necessary package metadata and dependencies. The dependencies have specific version constraints to ensure compatibility, and some dependencies enable specific features that are likely needed by the project.

The chosen dependencies suggest a well-thought-out design for the release helper tool, including:

  • clap for command-line argument parsing
  • git2 for interacting with Git repositories
  • semver for version parsing and comparison
  • serde and serde_json for JSON serialization and deserialization
  • toml and toml_edit for reading and writing TOML files

Overall, the package configuration and dependencies look good to me!

python/pyproject.toml (2)

27-27: LGTM!

Adding the build package as a dev dependency is a good practice for building and distributing the package. Pinning the version ensures reproducible builds.


29-29: LGTM!

Adding the twine package as a dev dependency is a good practice for publishing the package. Using the ~= version specifier allows for compatible releases while avoiding potential breaking changes.

releaser/src/check_binaries.rs (1)

17-21: LGTM!

The is_url_ok function is implemented correctly:

  • It creates a new blocking reqwest client.
  • Sends a HEAD request to the provided URL.
  • Returns true if the response status is in the success range.
  • The function signature and return type are appropriate.
  • Error handling is done using the Result type.
releaser/src/packages.rs (2)

7-10: LGTM!

The struct definition is clear and uses appropriate types for the fields.


52-54: LGTM!

The iter method provides a convenient way to iterate over the packages in the PackageList.

releaser/src/util.rs (1)

19-54: LGTM!

The BumpType enum is well-defined and follows Rust conventions. The Display trait implementation and the bump associated function are implemented correctly.

releaser/README.md (3)

12-27: LGTM!

The instructions for bumping the version are clear, accurate, and consistent with the expected process. The step-by-step guidance and the provided command will be helpful for developers.

Tools
Markdownlint

12-12: Expected: setext; Actual: atx
Heading style

(MD003, heading-style)


16-16: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)


29-36: Instructions are clear and informative.

The instructions for creating a release through GitHub Actions are well-written and provide the necessary information for developers. The link to the release workflow, the note about the version number, and the description of the expected outcome make the process easy to understand and follow.

Tools
Markdownlint

29-29: Expected: setext; Actual: atx
Heading style

(MD003, heading-style)


37-50: Publishing instructions are well-documented.

The instructions for publishing packages are clear and provide the necessary information for developers. The note about the package referring to the published binaries, the command to run the releaser program, and the list of steps performed by the program make the process easy to understand and follow.

Tools
Markdownlint

37-37: Expected: setext; Actual: atx
Heading style

(MD003, heading-style)


43-43: null
Fenced code blocks should have a language specified

(MD040, fenced-code-language)

releaser/src/package_manager/python/virtualenv.rs (4)

8-13: LGTM!

The function logic is correct, and the implementation is accurate. Using a random u64 value ensures a high probability of generating a unique directory path.


18-21: LGTM!

The struct definition is clear and well-documented. The fields are appropriately named and typed.


24-51: LGTM!

The method logic is correct, and the implementation is accurate. It properly creates a new virtual environment, installs the specified dependencies, and returns a new instance of VirtualEnv.


54-56: LGTM!

The method is a simple getter that returns the path to the Python executable. The implementation is correct.

releaser/src/git.rs (5)

11-14: LGTM!

The function logic is correct, and the implementation is accurate. Using Result for error handling is a good practice.


17-28: LGTM!

The function logic is correct, and the implementation is accurate. Using Result for error handling is a good practice.


30-38: LGTM!

The function logic is correct, and the implementation is accurate. Using Result for error handling and anyhow::bail! for custom errors is a good practice.


41-49: LGTM!

The function logic is correct, and the implementation is accurate. Using the git CLI for staging and committing changes is a reasonable approach, as it leverages the user's git configuration.


52-60: LGTM!

The function logic is correct, and the implementation is accurate. Using Result for error handling is a good practice.

releaser/src/main.rs (5)

1-13: LGTM!

The import statements and module declarations are well-structured and follow Rust's naming conventions. The usage of external crates and internal modules is appropriate for the project's functionality.


14-31: LGTM!

The command-line arguments are well-defined using the clap crate. The Bump and Publish subcommands provide a clear interface for the release process. The optional version argument for the Bump subcommand allows flexibility in manual version updates.


32-51: LGTM!

The main function sets up the PackageList with various packages in a clear and structured manner. The comment about the publishable order is helpful for maintaining the correct release sequence. The registration of packages using descriptive names and paths improves the readability and maintainability of the code.


52-58: LGTM!

The creation of the Releaser instance with the PackageList encapsulates the release process effectively. The parsing of command-line arguments using Args::parse() is consistent with the clap crate's API. The match expression provides a clear way to handle the different subcommands and their respective actions.


76-77: LGTM!

The closing braces for the match expression and the main function are in the correct position, and there are no syntax issues.

releaser/src/package_manager/cargo.rs (2)

116-122: Correct Logical Error in Dependency Version Update

In the update_dep_table function, there's a logical error where the existing version is reassigned instead of updating to the new version. The variable version inside the if let block shadows the function parameter version.

Apply this diff to fix the version assignment:

 if let Some(_) = dep_version.as_str() {
-    *dep_version = value(version.to_string());
+    *dep_version = value(version.to_string());
 } else if let Some(table) = dep_version.as_table_like_mut() {
-    table.insert("version", value(version.to_string()));
+    table["version"] = value(version.to_string());
 } else {
     continue;
 };

Make sure to remove the inner variable version to prevent shadowing and assign the new version correctly.

Likely invalid or redundant comment.


31-36: Handle Potential Parsing Errors in Response JSON

If the response from crates.io does not contain the expected fields, the code may fail when parsing. Consider adding error handling for missing or malformed data.

Run the following script to verify the structure of the response:

Ensure that the max_version field exists and is in the expected format.

Verification successful

API Response Structure Verified, Existing Error Handling Sufficient

The crates.io API response contains the expected max_version field in the correct location, matching the structure used in the code. The existing error handling (using context() and the ? operator) should adequately handle parsing issues for most cases.

If extremely robust error handling is desired, consider adding:

  • Validation of the max_version string to ensure it's a valid semantic version.
  • A check for the presence of the _crate and max_version fields before accessing them.
Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the crates.io API response contains the expected fields.

# Test: Fetch the package data and check for 'max_version' field.
# Replace 'package_name' with an actual package name for testing.
curl -s https://crates.io/api/v1/crates/package_name | jq '.crate.max_version'

Length of output: 86

releaser/src/packages.rs Show resolved Hide resolved
releaser/src/git.rs Outdated Show resolved Hide resolved
releaser/src/main.rs Show resolved Hide resolved
releaser/src/package_manager/mod.rs Show resolved Hide resolved
releaser/src/releaser.rs Outdated Show resolved Hide resolved
releaser/src/releaser.rs Show resolved Hide resolved
releaser/src/releaser.rs Show resolved Hide resolved
releaser/src/releaser.rs Show resolved Hide resolved
releaser/src/releaser.rs Show resolved Hide resolved
releaser/src/git.rs Outdated Show resolved Hide resolved
@rolyatmax
Copy link
Member

Left some comments re: some steps that were missed from this doc: https://www.notion.so/jamsocket/Y-sweet-release-checklist-e2d9fc60c0c143a2aa8ad2ddd4964e73

}

pub fn bump(&self, version: Option<Version>) -> Result<()> {
ensure_repo_ready(&self.git)?;
if !self.allow_dirty {
ensure_repo_ready(&self.git)?;
Copy link
Member

Choose a reason for hiding this comment

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

nit: should still probably never allow uncommitted changes (it's okay if the changes have been committed but aren't yet on main, though)

paulgb and others added 26 commits September 26, 2024 15:42
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
@paulgb paulgb merged commit 010647b into main Sep 26, 2024
10 checks passed
@paulgb paulgb deleted the paulgb/releaser branch September 26, 2024 19:44
@coderabbitai coderabbitai bot mentioned this pull request Sep 30, 2024
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