-
Notifications
You must be signed in to change notification settings - Fork 0
refactor: rewrite in effect #15
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
Conversation
This commit deletes the `_shared.ts` file and several test files that were no longer needed, including `changelog.authors.test.ts`, `changelog.test.ts`, `git.test.ts`, and `commits.test.ts`. The removed tests were primarily focused on creating mock data and testing functionalities that are either deprecated or have been refactored in other parts of the codebase. This cleanup helps streamline the test suite and reduces maintenance overhead.
|
Warning Rate limit exceeded@luxass has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 2 minutes and 32 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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. 📒 Files selected for processing (5)
Note Other AI code review bot(s) detectedCodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review. WalkthroughReplaces procedural release tooling with an Effect-based service architecture: many core modules and legacy versioning files removed; new services added for Git, GitHub, Workspace, Version calculation, Dependency graph, and Package updates; options normalization, typed errors, helper utilities, tests, and a consolidated createReleaseScripts entrypoint introduced. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant CLI as CLI (createReleaseScripts)
participant App as Index / AppLayer
participant Git as GitService
participant WS as WorkspaceService
participant GH as GitHubService
participant Calc as VersionCalculatorService
participant Graph as DependencyGraphService
participant Upd as PackageUpdaterService
CLI->>App: createReleaseScripts(options)
App->>Git: assertWorkspaceReady()
App->>WS: discoverWorkspacePackages()
WS-->>App: packages[]
App->>Git: get commits & file-changes
Git-->>App: commits, file-changes
App->>Calc: calculateBumps(packages, commits, overrides)
Calc-->>App: releases[]
App->>Graph: topologicalOrder(releases/packages)
Graph-->>App: orderedPlan
alt prepare + apply
App->>Upd: applyReleases(orderedPlan)
Upd->>Git: write package.json / stage / commit / push
Upd->>GH: upsertPullRequest(...)
else verify
App->>GH: getPullRequestByBranch(branch)
GH-->>App: PR or null
App->>Git: checkout branch (if needed)
end
App-->>CLI: result / exit
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
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. Comment |
- Removed the `HOW_IT_WORKS.md` documentation file. - Introduced `ConfigService` to manage configuration options more effectively. - Updated `createReleaseScripts` to utilize normalized options and improve clarity. - Enhanced `GitService` and `GitHubService` to integrate with the new configuration structure. - Added `options.ts` to define and normalize options for the release process. - Created a new `changelog.ts` file for future changelog management.
- Introduced `GitHubError` for better error handling in GitHub API interactions. - Refactored `GitService` to utilize `ConfigOptions` instead of `ConfigService`. - Added dry run mode to options, allowing for non-destructive testing of commands. - Enhanced `GitService` with new methods for branch management and command execution. - Created tests for `GitService` to ensure proper functionality and error handling.
… features - Added error handling for branch checkout in `playground.ts`. - Introduced `ExternalCommitParserError` and `OverridesLoadError` for better error management in `errors.ts`. - Updated `GitService` to include new methods for commit parsing and file reading. - Refactored `ConfigOptions` to improve configuration handling in `options.ts`. - Implemented new utility functions in `helpers.ts` for managing version overrides and merging commits. - Enhanced `WorkspaceService` to support discovering workspace packages and reading package.json files.
…tion - Added `DependencyGraphService` to manage package dependencies and their update order. - Introduced `VersionCalculatorService` to calculate version bumps based on commit types. - Created `PackageUpdaterService` to apply version updates to package.json files. - Refactored imports in `index.ts` to utilize new service structure. - Removed unused `changelog.ts` file. - Updated `package.json` to reflect new service imports.
- Introduced `ReleaseScriptsOptions` for improved configuration handling. - Refactored `createReleaseScripts` to utilize `ReleaseScriptsOptionsInput`. - Updated `GitService`, `GitHubService`, and `PackageUpdaterService` to use the new options structure. - Added `assertWorkspaceReady` method in `GitService` for workspace validation. - Removed deprecated `ConfigOptions` and related tests. - Added tests for `normalizeReleaseScriptsOptions` to ensure correct behavior.
…indCommitRange` functions This commit introduces a comprehensive suite of unit tests for the functions `isGlobalCommit`, `isDependencyFile`, and `findCommitRange` in the `helpers` module. The tests cover various scenarios to ensure the correctness of these functions, including edge cases and expected behaviors with different input conditions.
…indCommitRange` functions
…m-lock.yaml` This change cleans up the `pnpm-lock.yaml` file by removing the `@effect/cli` package and its associated dependencies, which are no longer needed. This helps to streamline the dependency graph and reduce potential conflicts in future updates.
This commit cleans up the code change entries by removing any empty `<code-changes>` tags. This helps maintain a tidy and organized structure in the change logs, ensuring that only relevant changes are documented.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR represents a complete rewrite of the release scripts library using the Effect functional programming library. The author notes they haven't written Effect code before, which is evident in some areas where patterns could be improved. The rewrite removes substantial functionality including all tests, the publish command, and extensive Git/GitHub utilities, while introducing a new service-based architecture.
Key changes include:
- Migration from imperative to Effect-based functional programming
- Introduction of service layer pattern (GitService, GitHubService, WorkspaceService, etc.)
- Complete removal of existing test suite
- Removal of publish functionality
- Simplified error handling using Effect's error types
Reviewed changes
Copilot reviewed 35 out of 37 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
src/index.ts |
New Effect-based API exposing verify, prepare, and publish (stub) methods |
src/options.ts |
Normalized options configuration with Effect Context.Tag |
src/verify.ts |
Rewritten verify command using Effect generators |
src/utils/helpers.ts |
Helper functions for commit processing and global commit detection |
src/services/git.service.ts |
Effect service wrapping Git operations |
src/services/github.service.ts |
Effect service for GitHub API interactions |
src/services/workspace.service.ts |
Effect service for workspace package discovery |
src/services/version-calculator.service.ts |
Effect service for version bump calculations |
src/services/dependency-graph.service.ts |
Effect service for dependency graph operations |
src/services/package-updater.service.ts |
Effect service for updating package.json files |
src/errors.ts |
Effect-based error types using Data.TaggedError |
test/options.test.ts |
New tests for options normalization |
test/helpers.test.ts |
New tests for helper functions |
tsconfig.json |
Added Effect language service plugin |
package.json |
Added Effect dependencies and updated imports |
| Multiple deleted files | Removed old implementation files, tests, and documentation |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Simplified the handling of `packages` by removing type assertions in the `calculateBumps` and `topologicalOrder` function calls. This improves type safety and clarity in the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 17
🧹 Nitpick comments (20)
playground.ts (1)
13-18: Consider simplifying the error handling and return.The
catchAlllogs and re-throws the same error, which adds little value. Also,return void 0is unconventional.- yield* git.branches.checkout("main").pipe(Effect.catchAll((err) => { - console.error(`Error checking out main branch: ${err.message}`); - return Effect.fail(err); - })); - - return void 0; + yield* git.branches.checkout("main").pipe( + Effect.tapError((err) => Effect.sync(() => console.error(`Error checking out main branch: ${err.message}`))) + );src/verify.ts (1)
59-62: Incomplete implementation noted.The TODO comments indicate remaining steps. Consider tracking these as issues or using
Effect.todoto make the incomplete state explicit in the type system.Would you like me to open an issue to track the remaining implementation steps (Steps 4-7)?
src/errors.ts (1)
26-47: Inconsistent use ofreadonlymodifier on error properties.The first five error classes use
readonlyfor their properties, butWorkspaceError,GitHubError,VersionCalculationError, andOverridesLoadErrordon't. For consistency and immutability, consider addingreadonlyto all properties.export class WorkspaceError extends Data.TaggedError("WorkspaceError")<{ - message: string; - operation?: string; - cause?: unknown; + readonly message: string; + readonly operation?: string; + readonly cause?: unknown; }> { } export class GitHubError extends Data.TaggedError("GitHubError")<{ - message: string; - operation?: "getPullRequestByBranch" | "createPullRequest" | "updatePullRequest" | "setCommitStatus" | "request"; - cause?: unknown; + readonly message: string; + readonly operation?: "getPullRequestByBranch" | "createPullRequest" | "updatePullRequest" | "setCommitStatus" | "request"; + readonly cause?: unknown; }> { } export class VersionCalculationError extends Data.TaggedError("VersionCalculationError")<{ - message: string; - packageName?: string; - cause?: unknown; + readonly message: string; + readonly packageName?: string; + readonly cause?: unknown; }> { } export class OverridesLoadError extends Data.TaggedError("OverridesLoadError")<{ - message: string; - cause?: unknown; + readonly message: string; + readonly cause?: unknown; }> {}src/services/git.service.ts (3)
43-51: Redundant.trim()call.Line 50 has
.map((line) => line.trim())after line 49 already trims with.replace(/^\* /, "").trim().const listBranches = Effect.gen(function* () { const output = yield* execGitCommand(["branch", "--list"]); return output .trim() .split("\n") .filter((line) => line.length > 0) - .map((line) => line.replace(/^\* /, "").trim()) - .map((line) => line.trim()); + .map((line) => line.replace(/^\* /, "").trim()); });
77-85: Use typed error instead of plainError.For consistency with the error handling pattern, use a typed error like
WorkspaceErrororGitErrorinstead of a plainError.+import { GitError, GitCommandError, ExternalCommitParserError } from "../errors"; +// ... (GitError already imported, may need WorkspaceError) + function stageChanges(files: readonly string[]) { return Effect.gen(function* () { if (files.length === 0) { - return yield* Effect.fail(new Error("No files to stage.")); + return yield* Effect.fail(new GitError({ message: "No files to stage." })); } return yield* execGitCommand(["add", ...files]); }); }
176-188: Use typed errors for workspace readiness checks.
GitNotRepositoryErrorandWorkspaceErrorare defined but not used here. This would enable better error handling downstream.+import { GitNotRepositoryError, WorkspaceError } from "../errors"; + const assertWorkspaceReady = Effect.gen(function* () { const withinRepo = yield* isWithinRepository; if (!withinRepo) { - return yield* Effect.fail(new Error("Not within a Git repository.")); + return yield* Effect.fail(new GitNotRepositoryError({ path: config.workspaceRoot })); } const clean = yield* isWorkingDirectoryClean; if (!clean) { - return yield* Effect.fail(new Error("Working directory is not clean.")); + return yield* Effect.fail(new WorkspaceError({ + message: "Working directory is not clean.", + operation: "assertWorkspaceReady" + })); } return true; });src/utils/helpers.ts (1)
284-297: Redundant null checks after length check.After checking
pkg.commits.length === 0and continuing, accessingpkg.commits[0]andpkg.commits[pkg.commits.length - 1]will always succeed. The subsequent null checks and throws are defensive but unreachable.for (const pkg of packages) { if (pkg.commits.length === 0) { continue; } - const firstCommit = pkg.commits[0]; - if (!firstCommit) { - throw new Error(`No commits found for package ${pkg.name}`); - } - - const lastCommit = pkg.commits[pkg.commits.length - 1]; - if (!lastCommit) { - throw new Error(`No commits found for package ${pkg.name}`); - } + const firstCommit = pkg.commits[0]!; + const lastCommit = pkg.commits[pkg.commits.length - 1]!;package.json (1)
46-47: Minor inconsistency in version pinning.
@effect/language-serviceuses a caret range (^0.60.0) while@effect/vitestuses exact pinning (0.27.0). Consider using consistent version pinning across Effect dev dependencies.- "@effect/language-service": "^0.60.0", + "@effect/language-service": "0.60.0",test/options.test.ts (1)
28-31: Consider adding test for whitespace-only token.The
normalizeReleaseScriptsOptionsfunction trims the token before validation, but there's no test verifying that a whitespace-only token is rejected.it("throws if githubToken is whitespace only", () => { expect(() => normalizeReleaseScriptsOptions({ repo: "octocat/hello-world", githubToken: " " })).toThrow(); });src/services/version-calculator.service.ts (2)
14-16: Guard against undefined in BUMP_PRIORITY lookup.If
incomingorcurrentcontains an unexpected value not inBUMP_PRIORITY, the comparison will fail silently. Add a fallback or type assertion.function maxBump(current: BumpKind, incoming: BumpKind): BumpKind { - return BUMP_PRIORITY[incoming] > BUMP_PRIORITY[current] ? incoming : current; + const incomingPriority = BUMP_PRIORITY[incoming] ?? 0; + const currentPriority = BUMP_PRIORITY[current] ?? 0; + return incomingPriority > currentPriority ? incoming : current; }
37-91: Consider bounded concurrency for large workspaces.Using
{ concurrency: "unbounded" }may cause resource exhaustion in large monorepos with many packages. Consider a reasonable bound or making it configurable.- { concurrency: "unbounded" }, + { concurrency: 10 },src/services/dependency-graph.service.ts (2)
55-56: Consider using a more efficient queue implementation.
queue.shift()is O(n) for arrays. For large dependency graphs, this could become a performance bottleneck. Consider using a proper queue structure or iterating with an index.+ let queueIndex = 0; const ordered: PackageUpdateOrder[] = []; - while (queue.length > 0) { - const current = queue.shift()!; + while (queueIndex < queue.length) { + const current = queue[queueIndex++];
79-81: Consider providing more context in cycle detection error.When a cycle is detected, identifying which packages are involved would help debugging.
if (ordered.length !== packages.length) { - return yield* Effect.fail(new Error("Cycle detected in workspace dependencies")); + const processed = new Set(ordered.map(o => o.package.name)); + const unprocessed = packages.filter(p => !processed.has(p.name)).map(p => p.name); + return yield* Effect.fail(new Error(`Cycle detected in workspace dependencies. Packages involved: ${unprocessed.join(", ")}`)); }src/options.ts (1)
4-6: DeepRequired type may not handle all cases correctly.The conditional
T[K] extends Required<T[K]>checks if the property is already required, but this doesn't correctly identify primitive types vs. objects that need deep transformation. Consider using a more robust implementation.-type DeepRequired<T> = Required<{ - [K in keyof T]: T[K] extends Required<T[K]> ? T[K] : DeepRequired<T[K]> -}>; +type DeepRequired<T> = T extends object + ? { [K in keyof T]-?: DeepRequired<T[K]> } + : T;src/services/package-updater.service.ts (1)
57-62: Consider providing more context in file write errors.The error is caught but loses context about which package failed. Wrap with additional information.
return Effect.tryPromise({ try: async () => { await fs.writeFile(fullPath, content, "utf8"); }, - catch: (e) => e as Error, + catch: (e) => new Error(`Failed to write ${fullPath}: ${(e as Error).message}`, { cause: e }), });src/services/github.service.ts (1)
124-127: Unused dependency:GitService.Default.
GitServiceis imported and declared as a dependency but is never used within theGitHubServiceimplementation. Consider removing it to avoid unnecessary coupling.-import { GitService } from "./git.service.js";- dependencies: [ - GitService.Default, - ], + dependencies: [],src/index.ts (1)
43-46: Type assertion masks potential dependency issues.The cast
as Effect.Effect<A, E, never>suppresses type-checking for the requirements parameterR. IfAppLayerdoesn't fully satisfy a program's dependencies, this will cause runtime errors rather than compile-time errors.Consider using
Effect.runPromisewith proper layer provision or definingAppLayerwith the correct type to ensure compile-time safety. Alternatively, document why this cast is necessary.src/services/workspace.service.ts (3)
80-101: Consider using@effect/platformFileSystem for consistency.The service uses
@effect/platform'sCommandExecutorfor running commands but uses Node.jsfs/promisesdirectly for file operations. For consistency and better testability, consider using@effect/platform'sFileSystemservice.
155-163: Dead code:excludedPackagesis populated but never used.The
excludedPackagesSet is created and populated but never read. Either remove it or use it for logging/debugging purposes.- const excludedPackages = new Set<string>(); ... - excludedPackages.add(rawProject.name);
243-243: Missing dependency declaration forCommandExecutor.The service uses
CommandExecutor.CommandExecutoron line 48 but doesn't declare it in the dependencies array. The service relies on theAppLayerinsrc/index.tsto provide this dependency, which works but makes the service less self-documenting and harder to test in isolation.Consider declaring the dependency explicitly:
- dependencies: [], + dependencies: [ + NodeCommandExecutor.layer, + ],
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (36)
.vscode/settings.json(1 hunks)HOW_IT_WORKS.md(0 hunks)package.json(2 hunks)playground.ts(1 hunks)src/core/changelog.ts(0 hunks)src/core/git.ts(0 hunks)src/core/github.ts(0 hunks)src/core/prompts.ts(0 hunks)src/core/workspace.ts(0 hunks)src/errors.ts(1 hunks)src/index.ts(1 hunks)src/options.ts(1 hunks)src/publish.ts(0 hunks)src/release.ts(0 hunks)src/services/dependency-graph.service.ts(1 hunks)src/services/git.service.ts(1 hunks)src/services/github.service.ts(1 hunks)src/services/package-updater.service.ts(1 hunks)src/services/version-calculator.service.ts(1 hunks)src/services/workspace.service.ts(1 hunks)src/shared/options.ts(0 hunks)src/shared/types.ts(0 hunks)src/shared/utils.ts(0 hunks)src/utils/helpers.ts(1 hunks)src/verify.ts(1 hunks)src/versioning/commits.ts(0 hunks)src/versioning/package.ts(0 hunks)src/versioning/version.ts(0 hunks)test/_shared.ts(0 hunks)test/core/changelog.authors.test.ts(0 hunks)test/core/changelog.test.ts(0 hunks)test/core/git.test.ts(0 hunks)test/helpers.test.ts(1 hunks)test/options.test.ts(1 hunks)test/versioning/commits.test.ts(0 hunks)tsconfig.json(1 hunks)
💤 Files with no reviewable changes (19)
- src/publish.ts
- src/versioning/commits.ts
- test/core/changelog.authors.test.ts
- test/versioning/commits.test.ts
- HOW_IT_WORKS.md
- src/core/workspace.ts
- src/shared/types.ts
- src/core/github.ts
- src/core/git.ts
- src/shared/utils.ts
- src/versioning/version.ts
- src/shared/options.ts
- test/core/git.test.ts
- src/core/changelog.ts
- src/core/prompts.ts
- test/core/changelog.test.ts
- src/release.ts
- test/_shared.ts
- src/versioning/package.ts
🧰 Additional context used
🧬 Code graph analysis (10)
src/services/dependency-graph.service.ts (1)
src/services/workspace.service.ts (1)
WorkspacePackage(34-34)
test/helpers.test.ts (1)
src/utils/helpers.ts (4)
WorkspacePackageWithCommits(84-84)isGlobalCommit(230-243)isDependencyFile(262-270)findCommitRange(280-315)
src/services/workspace.service.ts (1)
src/errors.ts (1)
WorkspaceError(26-30)
src/utils/helpers.ts (3)
src/services/git.service.ts (1)
GitService(8-219)src/errors.ts (1)
OverridesLoadError(44-47)src/services/workspace.service.ts (2)
WorkspacePackageSchema(25-32)WorkspacePackage(34-34)
playground.ts (1)
src/services/git.service.ts (1)
GitService(8-219)
src/services/version-calculator.service.ts (2)
src/utils/helpers.ts (1)
WorkspacePackageWithCommits(84-84)src/errors.ts (1)
VersionCalculationError(38-42)
test/options.test.ts (1)
src/options.ts (3)
ReleaseScriptsOptionsInput(8-35)normalizeReleaseScriptsOptions(45-110)ReleaseScriptsOptions(112-115)
src/services/git.service.ts (2)
src/options.ts (1)
ReleaseScriptsOptions(112-115)src/errors.ts (2)
GitCommandError(8-11)ExternalCommitParserError(13-16)
src/services/github.service.ts (2)
src/errors.ts (1)
GitHubError(32-36)src/services/git.service.ts (1)
GitService(8-219)
src/services/package-updater.service.ts (1)
src/services/workspace.service.ts (1)
WorkspacePackage(34-34)
🪛 GitHub Actions: CI
src/services/dependency-graph.service.ts
[error] 1-1: tsc --noEmit failed: Cannot find module '../shared/types' or its corresponding type declarations. (TS2307)
🪛 GitHub Check: build
src/services/dependency-graph.service.ts
[failure] 1-1:
Cannot find module '../shared/types' or its corresponding type declarations.
src/services/workspace.service.ts
[failure] 7-7:
Module '"../options"' has no exported member 'ConfigOptions'.
[failure] 1-1:
Cannot find module '#shared/types' or its corresponding type declarations.
src/services/version-calculator.service.ts
[failure] 15-15:
Object is possibly 'undefined'.
[failure] 15-15:
Object is possibly 'undefined'.
[failure] 1-1:
Cannot find module '../shared/types' or its corresponding type declarations.
src/services/github.service.ts
[failure] 3-3:
Module '"../options.js"' has no exported member 'ConfigOptions'.
src/services/package-updater.service.ts
[failure] 6-6:
Module '"../options"' has no exported member 'ConfigOptions'.
[failure] 1-1:
Cannot find module '../shared/types' or its corresponding type declarations.
🔇 Additional comments (25)
playground.ts (1)
21-30: Layer composition and execution look correct.The Effect layer composition follows standard patterns, providing dependencies in the correct order.
test/helpers.test.ts (5)
10-25: Well-designed test factory for creating mock commits.The
makeCommithelper creates realistic GitCommit objects with sensible defaults. Good use of hash padding for consistency.
27-46: Comprehensive package factory matching the schema.The
makePackagehelper correctly constructsWorkspacePackageWithCommitsobjects with all required fields.
48-90: Thorough test coverage forisGlobalCommit.Good coverage of edge cases including partial path prefix matching (line 82-85), empty inputs, and
./prefix normalization.
92-160: Good coverage of dependency file detection.Tests appropriately cover root-level files, nested paths, rejection of similar names, and edge cases.
162-283: ComprehensivefindCommitRangetest suite.Good coverage of edge cases including empty packages, out-of-order commits, same timestamps, and timezone offsets. The same-timestamp test appropriately documents the iteration-order dependency.
src/verify.ts (1)
14-63: Effect-based program construction follows good patterns.The function correctly separates program definition from layer provision, allowing callers to provide dependencies. The service wiring is clean.
src/errors.ts (1)
3-24: Well-structured tagged error classes.Good use of
Data.TaggedErrorwith descriptive tags and contextual payloads. The specific error types will enable precise error handling with Effect'scatchTag.src/services/git.service.ts (1)
190-219: Clean API structure and service definition.The API is well-organized with logical groupings. The
as constassertion ensures type safety, and dependencies are correctly declared.src/utils/helpers.ts (2)
53-84: Well-defined schemas for commits and packages.The
GitCommitSchemaandWorkspacePackageWithCommitsSchemaare properly structured with appropriate types and defaults.
230-270: Helper functionsisGlobalCommitandisDependencyFileare well-implemented.The path normalization and matching logic correctly handles edge cases like
./prefixes and partial path matches..vscode/settings.json (1)
1-3: LGTM!Standard VSCode configuration to use the workspace TypeScript version, which is required for the
@effect/language-serviceplugin to function correctly.tsconfig.json (1)
17-21: LGTM!Adding the
@effect/language-serviceplugin enhances IDE support for Effect-based code with better type inference and diagnostics.package.json (1)
33-44: LGTM!Effect ecosystem dependencies are properly added. The exact version pinning for runtime dependencies (
@effect/platform,@effect/platform-node,effect) is good for reproducibility.test/options.test.ts (2)
1-8: LGTM!Clean imports and proper use of
@effect/vitestfor Effect-based testing.
72-102: LGTM on Effect DI tests.Good use of
it.effectandEffect.provideServiceto test the Context.Tag-based dependency injection pattern.src/services/package-updater.service.ts (1)
8-18: LGTM on nextRange implementation.Correctly handles
workspace:prefix preservation and range specifiers (^,~). The*andlatestwildcards are properly preserved.src/services/github.service.ts (2)
7-56: LGTM!The schema definitions are well-structured and follow Effect's Schema patterns correctly. The use of
Schema.NullOrfor nullable fields andSchema.optionalfor optional fields is appropriate.
62-105: LGTM with a note on type safety.The
makeRequesthelper is well-implemented with proper error handling, schema validation, and 204 response handling. Theundefined as Acast on line 92 is a pragmatic workaround for endpoints that return no content.src/index.ts (3)
48-59: LGTM!The safeguard pattern validates workspace readiness during initialization, providing early failure with a clear error message. Good defensive programming.
121-140: LGTM!The
packagesnamespace provides clean delegations toWorkspaceServicewith appropriate null handling for missing packages.
32-41: Layer composition order is correct; services receive the configuration as expected.The pattern
Layer.succeed(ReleaseScriptsOptions, config).pipe(Layer.provide(GitService.Default), ...)is semantically correct. In Effect,A.pipe(Layer.provide(B))builds layer B first, then uses its outputs to satisfy A's requirements. Here,ReleaseScriptsOptionsis created without dependencies, then provided to services that require it (likeGitService, which yieldsReleaseScriptsOptionsat line 11 of git.service.ts). The composition order is not inverted—dependencies flow correctly from the configuration through to dependent services.Likely an incorrect or invalid review comment.
src/services/workspace.service.ts (3)
9-44: LGTM!The schema definitions accurately model the
package.jsonstructure and pnpm workspace output. Good use ofSchema.optionalfor fields that may not be present.
51-78: LGTM!Good use of
Effect.cachedto memoize the expensivepnpm lsoperation. The error handling properly wraps failures with operation context.
203-226: LGTM!The filtering logic is clear and handles all cases correctly with appropriate early returns.
…ted interfaces - Added `FindWorkspacePackagesOptions` interface to encapsulate package inclusion/exclusion logic. - Updated `ReleaseScriptsOptionsInput` to utilize `FindWorkspacePackagesOptions` for better clarity and structure. - Introduced `PackageUpdateOrder` interface with a new `level` property for dependency management. - Refactored imports in various services to use `ReleaseScriptsOptions` instead of `ConfigOptions` for consistency. - Added `PackageRelease` interface to define the structure of package updates, including versioning details and change indicators.
There was a problem hiding this 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
♻️ Duplicate comments (3)
src/options.ts (2)
69-72: Handle repos with multiple slashes more robustly.The current implementation using
split("/")with array destructuring will drop additional path segments if the repo string contains more than one slash (e.g.,"org/group/repo"). This edge case should be handled as previously suggested.Apply the previously suggested fix:
- const [owner, repo] = fullRepo.split("/"); + const [owner, ...repoParts] = fullRepo.split("/"); + const repo = repoParts.join("/"); if (!owner || !repo) { throw new Error(`Invalid repo format: "${fullRepo}". Expected format: "owner/repo" (e.g., "octocat/hello-world").`); }
47-111: User-providedtypesoption is ignored.The
typesparameter is destructured on line 48 but never used. The returned configuration always uses the hardcoded type mappings (lines 103-110), ignoring any custom types provided by the user.Apply the previously suggested fix to merge user-provided types with defaults:
+ const defaultTypes = { + feat: { title: "🚀 Features" }, + fix: { title: "🐞 Bug Fixes" }, + refactor: { title: "🔧 Code Refactoring" }, + perf: { title: "🏎 Performance" }, + docs: { title: "📚 Documentation" }, + style: { title: "🎨 Styles" }, + }; + return { // ... other properties - types: { - feat: { title: "🚀 Features" }, - fix: { title: "🐞 Bug Fixes" }, - refactor: { title: "🔧 Code Refactoring" }, - perf: { title: "🏎 Performance" }, - docs: { title: "📚 Documentation" }, - style: { title: "🎨 Styles" }, - }, + types: types ? { ...defaultTypes, ...types } : defaultTypes, };src/services/github.service.ts (1)
106-117: URL construction bug: double/repos/prefix.The
makeRequesthelper on line 62 constructs URLs ashttps://api.github.com/repos/${config.owner}/${config.repo}/${endpoint}. On line 108, the endpoint includes/repos/${config.owner}/${config.repo}/again, resulting in a malformed URL like:
https://api.github.com/repos/owner/repo/repos/owner/repo/pulls?...This will return 404 errors.
Apply the previously suggested fix:
function getPullRequestByBranch(branch: string) { const head = branch.includes(":") ? branch : `${config.owner}:${branch}`; - const url = `/repos/${config.owner}/${config.repo}/pulls?state=open&head=${encodeURIComponent(head)}`; - return makeRequest(url, Schema.Array(PullRequestSchema)).pipe( + return makeRequest(`pulls?state=open&head=${encodeURIComponent(head)}`, Schema.Array(PullRequestSchema)).pipe( Effect.map((pulls) => (pulls.length > 0 ? pulls[0] : null)),
🧹 Nitpick comments (2)
src/services/version-calculator.service.ts (2)
37-91: Consider bounded concurrency for large monorepos.Using
concurrency: "unbounded"may cause memory pressure or resource exhaustion in repositories with many packages (50+). Consider using a bounded concurrency value (e.g., 10 or 20) to limit parallel operations.Apply this diff:
), - { concurrency: "unbounded" }, + { concurrency: 20 }, );
72-72: TODO: Interactive version prompts.The comment indicates a planned feature for interactive version selection when
prompts.versionsis enabled. This is currently not implemented.Would you like me to open a tracking issue for this feature, or help implement the interactive prompt logic?
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
src/options.ts(1 hunks)src/services/dependency-graph.service.ts(1 hunks)src/services/github.service.ts(1 hunks)src/services/package-updater.service.ts(1 hunks)src/services/version-calculator.service.ts(1 hunks)src/services/workspace.service.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/services/dependency-graph.service.ts
- src/services/workspace.service.ts
🧰 Additional context used
🧬 Code graph analysis (3)
src/services/github.service.ts (3)
src/options.ts (1)
ReleaseScriptsOptions(114-117)src/errors.ts (1)
GitHubError(32-36)src/services/git.service.ts (1)
GitService(8-219)
src/services/version-calculator.service.ts (3)
src/services/package-updater.service.ts (2)
BumpKind(42-42)PackageRelease(43-68)src/utils/helpers.ts (1)
WorkspacePackageWithCommits(84-84)src/errors.ts (1)
VersionCalculationError(38-42)
src/services/package-updater.service.ts (2)
src/services/workspace.service.ts (1)
WorkspacePackage(34-34)src/options.ts (1)
ReleaseScriptsOptions(114-117)
…ate test cases - Removed unnecessary type assertions in `createReleaseScripts` for better type safety. - Updated test cases in `options.test.ts` to remove type assertions for `repo` parameter.
This update introduces a new `types` property to the `ReleaseScriptsOptionsInput` interface, allowing users to customize the types of changes in their release scripts. The default types are now merged with any user-defined types, providing greater flexibility in defining the structure of release notes.
Updated the `getMostRecentPackageTag` function to sort the tags in descending order by version using the `--sort=-version:refname` option. This change ensures that the most recent version tag is returned first, improving the accuracy of version retrieval for packages.
Updated the error handling in `WorkspaceService` to log a warning message when an invalid package is encountered, improving debugging and visibility into package processing issues.
Modified the `loadOverrides` function to pass the `options.sha` parameter to the `readFile` method, ensuring the correct version of the overrides file is read based on the specified SHA.
Refactor the `loadOverrides` function to streamline error handling when reading and parsing the overrides file. The new implementation uses `Effect.try` to directly handle JSON parsing errors, improving clarity and reducing unnecessary checks.
- Adjusted `mergePackageCommitsIntoPackages` to use `lastTag?.name` for fetching commits. - Modified `mergeCommitsAffectingGloballyIntoPackage` to utilize `lastTag.sha.slice(0, 7)` for cutoff timestamp calculation.
There was a problem hiding this 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
♻️ Duplicate comments (4)
src/options.ts (1)
55-113: Nice: usertypesare now honored and merged with defaults.The
types: options.types ? { ...DEFAULT_TYPES, ...types } : DEFAULT_TYPESmerge correctly lets callers override or extend the default sections without losing the base mapping, fixing the earlier issue whereoptions.typeswas ignored.src/utils/helpers.ts (1)
17-32:loadOverridesnow reads from the correct git ref and simplifies error handling.Switching to
git.workspace.readFile(options.overridesPath, options.sha)and catching parse/read errors once, returning{}on failure, makes this helper much clearer and fixes the earlier bug where"utf8"was used as the ref.src/services/git.service.ts (1)
104-113: Latest tag selection is reversed after adding--sort=-version:refname.With
git tag --list --sort=-version:refname, the newest tag is already first. Callingreverse()[0]now returns the oldest tag, sogetMostRecentPackageTagwill pick the wrong release and misdrive versioning logic.You can drop the
reverse()and take the first entry:function getMostRecentPackageTag(packageName: string) { return execGitCommand(["tag", "--list", "--sort=-version:refname", `${packageName}@*`]).pipe( Effect.map((tags) => { const tagList = tags .trim() .split("\n") .map((tag) => tag.trim()) .filter((tag) => tag.length > 0); - return tagList.reverse()[0] || null; + return tagList[0] || null; }),src/services/workspace.service.ts (1)
51-78:workspacePackageListOutputis executed eagerly and then treated as an Effect.Using
yield*here runs thepnpm lseffect during service construction and stores its result; later,findWorkspacePackagescalls.pipeon that value, which will fail at type‑check/runtime.You want a cached Effect instead:
- const workspacePackageListOutput = yield* executor.string(Command.make("pnpm", "-r", "ls", "--json").pipe( - Command.workingDirectory(config.workspaceRoot), - )).pipe( + const workspacePackageListOutput = executor.string(Command.make("pnpm", "-r", "ls", "--json").pipe( + Command.workingDirectory(config.workspaceRoot), + )).pipe( Effect.flatMap((stdout) => Effect.try({ try: () => JSON.parse(stdout), @@ ), - Effect.cached, - ); + Effect.cached, + );This keeps
workspacePackageListOutputas a lazily‑run, cached Effect thatfindWorkspacePackagescan safely.pipe(...).
🧹 Nitpick comments (3)
src/services/workspace.service.ts (1)
151-204: UnusedexcludedPackagestracking.
excludedPackagesis populated but never read, so it currently adds no value. Either log/report it or remove it to keep the implementation minimal:- return workspacePackageListOutput.pipe( - Effect.flatMap((rawProjects) => { - const allPackageNames = new Set<string>(rawProjects.map((p) => p.name)); - const excludedPackages = new Set<string>(); + return workspacePackageListOutput.pipe( + Effect.flatMap((rawProjects) => { + const allPackageNames = new Set<string>(rawProjects.map((p) => p.name)); @@ - if (!shouldIncludePackage(packageJson, options)) { - excludedPackages.add(rawProject.name); - return Effect.succeed(null); - } + if (!shouldIncludePackage(packageJson, options)) { + return Effect.succeed(null); + }src/options.ts (1)
4-6:DeepRequireddoesn’t actually removeundefinedfrom nested fields.The current definition mostly makes keys required but keeps value types like
string | undefinedunchanged, soNormalizedReleaseScriptsOptionsisn’t truly “deeply required”. This can weaken type safety aroundconfig.branch,config.pullRequest, etc.If you want a stricter normalized config type, consider a more conventional version:
type DeepRequired<T> = { [K in keyof T]-?: T[K] extends object ? DeepRequired<NonNullable<T[K]>> : NonNullable<T[K]>; };This keeps runtime behavior the same but makes the types better reflect that
normalizeReleaseScriptsOptionsfills all defaults.src/index.ts (1)
43-46: Avoidas Effect.Effect<A, E, never>by tightening the environment type.The cast in
runProgramdrops the real environment requirement, so ifAppLayerever stops providing something, TypeScript won’t catch it.You can make this type‑safe by introducing an explicit environment type and constraining
program:type ReleaseScriptsEnv = Effect.Effect.Context<ReturnType<typeof AppLayer>>; // or a manual intersection of the services you provide const runProgram = <A>( program: Effect.Effect<A, unknown, ReleaseScriptsEnv>, ): Promise<A> => { const provided = program.pipe(Effect.provide(AppLayer)); return Effect.runPromise(provided); };That way, missing services show up as type errors instead of being masked by
as.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
src/index.ts(1 hunks)src/options.ts(1 hunks)src/services/git.service.ts(1 hunks)src/services/github.service.ts(1 hunks)src/services/workspace.service.ts(1 hunks)src/utils/helpers.ts(1 hunks)test/options.test.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- test/options.test.ts
🧰 Additional context used
🧬 Code graph analysis (4)
src/services/github.service.ts (3)
src/options.ts (1)
ReleaseScriptsOptions(116-119)src/errors.ts (1)
GitHubError(32-36)src/services/git.service.ts (1)
GitService(8-230)
src/services/git.service.ts (2)
src/options.ts (1)
ReleaseScriptsOptions(116-119)src/errors.ts (2)
GitCommandError(8-11)ExternalCommitParserError(13-16)
src/services/workspace.service.ts (2)
src/options.ts (2)
ReleaseScriptsOptions(116-119)FindWorkspacePackagesOptions(8-12)src/errors.ts (1)
WorkspaceError(26-30)
src/index.ts (7)
src/services/workspace.service.ts (2)
WorkspacePackage(34-34)WorkspaceService(46-248)src/options.ts (3)
ReleaseScriptsOptionsInput(14-37)normalizeReleaseScriptsOptions(55-114)ReleaseScriptsOptions(116-119)src/services/git.service.ts (1)
GitService(8-230)src/services/github.service.ts (1)
GitHubService(57-125)src/services/dependency-graph.service.ts (1)
DependencyGraphService(9-97)src/verify.ts (1)
constructVerifyProgram(14-64)src/utils/helpers.ts (3)
loadOverrides(17-34)mergePackageCommitsIntoPackages(69-96)mergeCommitsAffectingGloballyIntoPackage(129-204)
🔇 Additional comments (3)
src/index.ts (1)
65-113: prepare() flow composes services coherently.The prepare program reuses the verify‑like checks (PR existence, branch checkout), wires in overrides, discovers packages, merges commits (including global ones), computes bumps and dependency order, and finally calls
packageUpdater.applyReleases. Structurally this is a solid Effect‑based orchestration and fits well with the new service layout.src/services/github.service.ts (1)
61-103: makeRequest helper is a good centralization of GitHub API concerns.The helper correctly builds the repo‑scoped URL, attaches auth and UA headers, handles 204 responses, and decodes via a provided schema while wrapping network and decode failures in
GitHubError. This sets you up nicely for adding create/update/status endpoints later.src/utils/helpers.ts (1)
69-96: mergePackageCommitsIntoPackages: good use of GitService and schema validation.Fetching per‑package commits from the last tag to
HEAD, enriching the workspace package, and validating viaWorkspacePackageWithCommitsSchemais a clean way to bind Git data into your domain type. The explicit error message on decode failure will be helpful for debugging.
…to allow null values
…fectingGloballyIntoPackage` Updated the calculation of `cutoffTimestamp` to use the full SHA from `lastTag` instead of slicing it. This ensures accurate retrieval of commit timestamps for the most recent tag associated with a package.
…tingGloballyIntoPackage` Replaced the use of `commit.shortHash` with `commit.hash` for accurate timestamp and affected files retrieval. This change ensures that the correct commit information is used when filtering commits that occurred after a package's last release.
There was a problem hiding this 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
♻️ Duplicate comments (3)
src/services/github.service.ts (1)
6-23: Pull requestbodyfield should allownullto handle valid API responses.GitHub's REST API returns
body: nullfor PRs without a description. The currentSchema.Stringdefinition will fail decoding even though the response is valid. This pattern is already correctly used formergeableon line 20.export const PullRequestSchema = Schema.Struct({ number: Schema.Number, title: Schema.String, - body: Schema.String, + body: Schema.NullOr(Schema.String), head: Schema.Struct({src/services/git.service.ts (1)
104-127: Tag sorting and selection logic is inconsistent.The command uses
--sort=-version:refname(descending order, newest first) but then calls.reverse()[0]which would return the oldest tag. This contradicts the likely intent to get the most recent tag.function getMostRecentPackageTag(packageName: string) { return execGitCommand(["tag", "--list", "--sort=-version:refname", `${packageName}@*`]).pipe( Effect.map((tags) => { const tagList = tags .trim() .split("\n") .map((tag) => tag.trim()) .filter((tag) => tag.length > 0); - return tagList.reverse()[0] || null; + return tagList[0] || null; }),src/utils/helpers.ts (1)
157-179: Hash key inconsistency betweencommitTimestampsand lookups.
commitTimestampsis keyed byshortHash(line 159), but lookups on lines 174 and 179 usecommit.hash(full hash). This mismatch means lookups will fail and returnundefined.// Used for quick lookup of commit timestamps/cutoffs const commitTimestamps = new Map( - allCommits.map((c) => [c.shortHash, new Date(c.date).getTime()]), + allCommits.map((c) => [c.hash, new Date(c.date).getTime()]), );Alternatively, if
shortHashis preferred, update lines 174 and 179 to usecommit.shortHash. The key choice should be consistent throughout.
🧹 Nitpick comments (3)
src/services/git.service.ts (2)
43-51: Redundant.map((line) => line.trim())call.Line 50 trims lines that were already trimmed on line 49.
const listBranches = Effect.gen(function* () { const output = yield* execGitCommand(["branch", "--list"]); return output .trim() .split("\n") .filter((line) => line.length > 0) - .map((line) => line.replace(/^\* /, "").trim()) - .map((line) => line.trim()); + .map((line) => line.replace(/^\* /, "").trim()); });
187-199: Consider using custom tagged errors for workspace assertions.The
assertWorkspaceReadyfunction uses genericErrorinstances. For consistency with the rest of the codebase's error handling pattern (usingData.TaggedError), consider defining specific error types.src/utils/helpers.ts (1)
263-298:findCommitRangehas defensive checks that can't trigger.Lines 273-275 and 278-280 throw errors if
firstCommitorlastCommitare falsy, but these cases are already guarded by thepkg.commits.length === 0check on line 268. The throws are unreachable. Consider removing them or simplifying the logic.for (const pkg of packages) { if (pkg.commits.length === 0) { continue; } - const firstCommit = pkg.commits[0]; - if (!firstCommit) { - throw new Error(`No commits found for package ${pkg.name}`); - } - - const lastCommit = pkg.commits[pkg.commits.length - 1]; - if (!lastCommit) { - throw new Error(`No commits found for package ${pkg.name}`); - } + const firstCommit = pkg.commits[0]!; + const lastCommit = pkg.commits[pkg.commits.length - 1]!;
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/services/git.service.ts(1 hunks)src/services/github.service.ts(1 hunks)src/utils/helpers.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/services/git.service.ts (2)
src/options.ts (1)
ReleaseScriptsOptions(116-119)src/errors.ts (2)
GitCommandError(8-11)ExternalCommitParserError(13-16)
src/services/github.service.ts (3)
src/options.ts (1)
ReleaseScriptsOptions(116-119)src/errors.ts (1)
GitHubError(32-36)src/services/git.service.ts (1)
GitService(8-230)
🔇 Additional comments (16)
src/services/git.service.ts (6)
1-6: Imports look correct and minimal.The imports align with the service's responsibilities: command execution from
@effect/platform, commit parsing, and custom error types.
8-23: Service setup and error mapping look good.The Effect.Service pattern is correctly implemented with proper dependency injection of
CommandExecutorandReleaseScriptsOptions. Error mapping toGitCommandErrorpreserves command context.
25-34: Dry-run helper design is sound.The conditional assignment pattern cleanly separates dry-run behavior. The comment clarifies intent well.
129-146: External commit parser integration is well-wrapped.The
Effect.tryPromisepattern correctly bridges the async library call, and errors are wrapped in the customExternalCommitParserErrortype with preserved cause information.
148-185: File-to-commit mapping implementation is solid.The parsing logic correctly handles git log output format, filters empty lines, and associates files with their respective commit hashes. The regex for SHA detection is appropriate.
201-230: API surface is well-organized.The grouped namespace structure (
branches,commits,tags,workspace) provides a clear and discoverable API. Dependencies are correctly declared.src/services/github.service.ts (3)
25-55: Schemas and type exports are well-defined.The schema definitions for PR options, commit status, and repository info are appropriate. The derived type exports provide good TypeScript integration.
61-104: ThemakeRequesthelper is well-implemented.Good error handling with proper status checking, 204 handling, and schema validation. The error wrapping into
GitHubErrorwith operation metadata is consistent.
106-116:getPullRequestByBranchimplementation looks correct.The head formatting logic and error mapping are appropriate. The null coalescing for empty results is handled correctly.
src/utils/helpers.ts (7)
1-10: Imports and interface definition look good.The imports are appropriate for the helper utilities, and
VersionOverridesprovides a clear type for the overrides map.
17-34:loadOverridesimplementation is clean and handles errors gracefully.The function correctly uses
GitService, reads from the specified ref, parses JSON, and falls back to an empty object on any error. This is a good resilient pattern.
36-66: Commit and package schemas are well-structured.The
GitCommitSchemacaptures all relevant commit metadata, andWorkspacePackageWithCommitsSchemaproperly extends the base schema with commit arrays.
69-96:mergePackageCommitsIntoPackagesimplementation is correct.The function properly retrieves the most recent tag per package, fetches commits since that tag, and validates the result against the schema.
165-168: Potential hash format mismatch for tag SHA lookup.
lastTag.shafromgetMostRecentPackageTagreturns the full SHA (viagit rev-parse). If you standardizecommitTimestampson full hashes (as suggested above), this lookup will work correctly. Verify thatlastTag.shaformat matches the chosen key format.
213-226:isGlobalCommitlogic is correct.The function properly normalizes paths and checks whether files fall outside all package directories.
245-253:isDependencyFilemay have false positives.The check
normalized.endsWith(/${dep})would match any path ending with the dependency filename, including nested directories likesome/deep/path/package.json. This is likely intentional for monorepo structures, but worth confirming.
Refactor the `writeCommit` and `pushChanges` functions to directly return the result of `execGitCommandIfNotDry`, removing unnecessary generator functions. This change improves code readability and maintains the existing functionality.
… ranges Updated the `nextRange` function to check if the new version satisfies existing complex ranges using `semver.satisfies`. If the new version is outside the existing range, an error is thrown to prevent silent failures. This change lays the groundwork for future implementation of range updating logic.
…aceService` - Moved the `writePackageJson` function to `WorkspaceService` for better modularity. - Updated `PackageUpdaterService` to utilize the new `writePackageJson` method, improving code organization and maintainability.
Improves the `maxBump` function by explicitly calculating the priorities of `incoming` and `current` bump types. This change enhances readability and maintainability of the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 34 out of 36 changed files in this pull request and generated 5 comments.
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const currentBranch = yield* git.branches.get; | ||
| if (currentBranch !== config.branch.default) { | ||
| yield* git.branches.checkout(config.branch.default); | ||
| yield* Console.log(`✅ Checked out to default branch "${config.branch.default}".`); | ||
| } | ||
|
|
||
| const overrides = yield* loadOverrides({ | ||
| sha: releasePullRequest.head.sha, | ||
| overridesPath: ".github/ucdjs-release.overrides.json", | ||
| }); | ||
|
|
||
| yield* Console.log("Loaded overrides:", overrides); | ||
|
|
||
| const packages = (yield* workspace.discoverWorkspacePackages.pipe( | ||
| Effect.flatMap(mergePackageCommitsIntoPackages), | ||
| Effect.flatMap((pkgs) => mergeCommitsAffectingGloballyIntoPackage(pkgs, config.globalCommitMode)), | ||
| )); | ||
|
|
||
| yield* Console.log("Discovered packages with commits and global commits:", packages); | ||
|
|
||
| const releases = yield* versionCalculator.calculateBumps(packages, overrides); | ||
| const ordered = yield* dependencyGraph.topologicalOrder(packages); | ||
|
|
||
| yield* Console.log("Calculated releases:", releases); | ||
| yield* Console.log("Release order:", ordered); | ||
|
|
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The verify and prepare programs have identical structure and duplicated code. Both checkout the default branch, load overrides, discover packages with commits, and calculate releases. Consider extracting this shared logic into a common helper function to reduce duplication and ensure consistency.
| const currentBranch = yield* git.branches.get; | |
| if (currentBranch !== config.branch.default) { | |
| yield* git.branches.checkout(config.branch.default); | |
| yield* Console.log(`✅ Checked out to default branch "${config.branch.default}".`); | |
| } | |
| const overrides = yield* loadOverrides({ | |
| sha: releasePullRequest.head.sha, | |
| overridesPath: ".github/ucdjs-release.overrides.json", | |
| }); | |
| yield* Console.log("Loaded overrides:", overrides); | |
| const packages = (yield* workspace.discoverWorkspacePackages.pipe( | |
| Effect.flatMap(mergePackageCommitsIntoPackages), | |
| Effect.flatMap((pkgs) => mergeCommitsAffectingGloballyIntoPackage(pkgs, config.globalCommitMode)), | |
| )); | |
| yield* Console.log("Discovered packages with commits and global commits:", packages); | |
| const releases = yield* versionCalculator.calculateBumps(packages, overrides); | |
| const ordered = yield* dependencyGraph.topologicalOrder(packages); | |
| yield* Console.log("Calculated releases:", releases); | |
| yield* Console.log("Release order:", ordered); | |
| // Use shared helper to resolve release state | |
| const { packages, releases, ordered, overrides } = yield* resolveReleaseState({ | |
| git, | |
| workspace, | |
| versionCalculator, | |
| dependencyGraph, | |
| config, | |
| sha: releasePullRequest.head.sha, | |
| }); |
…ctor queue processing Refactor the queue processing in `topologicalOrder` to use an index instead of shifting elements, enhancing performance. Additionally, improve the error message for cycle detection to include the names of unprocessed packages, providing better context for debugging.
Changed the commit timestamp lookup in `mergeCommitsAffectingGloballyIntoPackage` to utilize the full `hash` instead of `shortHash`. This improves the accuracy of commit identification during the merge process.
This PR rewrites the entire release scripts library in effect. There is probably a lot of things, that could be done way better, since i haven't written any effect before.
Summary by CodeRabbit
New Features
Changes
Documentation
Chores
Tests
✏️ Tip: You can customize this high-level summary in your review settings.