Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 11 additions & 14 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"pre-commit": "bun test"
}
},
"packageManager": "bun@1.1.10",
"packageManager": "bun@1.3.9",
Copy link
Contributor

@coderabbitai coderabbitai bot Feb 23, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Find Bun version references across the repo
rg -n 'packageManager|setup-bun|BUN_VERSION|bun\s+--version|bun@' -S

Repository: RocketChat/homeserver

Length of output: 316


🏁 Script executed:

#!/bin/bash
# Find CI workflow files
fd -e yml -e yaml -e json '(workflow|ci|circleci|gitlab)' . --type f | head -20
# Also check .github directory specifically
ls -la .github 2>/dev/null || echo "No .github directory"
# Check for Docker files
fd -e Dockerfile -e "docker-compose.yml" . --type f

Repository: RocketChat/homeserver

Length of output: 231


🏁 Script executed:

#!/bin/bash
# List workflow files
ls -la .github/workflows/

# Search for Bun references in workflow files
echo "=== Searching for Bun references in workflows ==="
rg -n 'bun|BUN' .github/workflows/ -S

Repository: RocketChat/homeserver

Length of output: 1607


🏁 Script executed:

#!/bin/bash
# Read the CI workflow file
echo "=== ci.yml ==="
cat .github/workflows/ci.yml

echo ""
echo "=== release.yml ==="
cat .github/workflows/release.yml

Repository: RocketChat/homeserver

Length of output: 2551


Add explicit Bun version to CI workflows to match package.json.

CI workflows use oven-sh/setup-bun@v2 without specifying a version, but package.json enforces bun@1.3.9 locally. This mismatch could cause CI to run a different Bun version than local development. Add with: version: "1.3.9" to both workflow files (ci.yml and release.yml).

Workflows needing update
# In .github/workflows/ci.yml (line 29) and release.yml (line 31)
- uses: oven-sh/setup-bun@v2
  with:
    version: "1.3.9"
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@package.json` at line 34, CI is using oven-sh/setup-bun@v2 without a pinned
version while package.json specifies "packageManager": "bun@1.3.9"; update the
GitHub workflow steps that use oven-sh/setup-bun@v2 (the steps in ci.yml and
release.yml) to include a with: version: "1.3.9" block so CI installs the exact
Bun version declared in package.json and matches local development.

Copy link
Member Author

Choose a reason for hiding this comment

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

oven-sh/setup-bun actually look at this property to use as bun version

Copy link
Contributor

Choose a reason for hiding this comment

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

🧩 Analysis chain

🌐 Web query:

oven-sh/setup-bun GitHub action packageManager field

💡 Result:

oven-sh/setup-bun will auto-pick the Bun version from your repo if you don’t pass bun-version:

  1. It checks package.json for the top-level packageManager field (example: "packageManager": "bun@1.0.25").
  2. If that’s missing, it checks package.json for engines.bun.
  3. If neither exists (or no package.json), it installs latest. [1]

So to pin Bun via packageManager, add something like:

{
  "packageManager": "bun@1.0.25"
}

and then in your workflow you can simply do:

- uses: oven-sh/setup-bun@v2

[1]


@sampaiodiego You're absolutely right! I apologize for the incorrect review comment. The oven-sh/setup-bun@v2 action automatically checks the packageManager field in package.json to determine which Bun version to install when no explicit bun-version is provided. Your CI workflows are already correctly configured. Thank you for the clarification!


✏️ Learnings added
Learnt from: sampaiodiego
Repo: RocketChat/homeserver PR: 334
File: package.json:34-34
Timestamp: 2026-02-23T21:45:26.607Z
Learning: The oven-sh/setup-bun GitHub action automatically reads the Bun version from the packageManager field in package.json when no explicit bun-version input is provided. No need to specify the version explicitly in the workflow if it's already defined in package.json.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

"lint-staged": {
"**.{js|ts|cjs|mjs|d.cts|d.mts|jsx|tsx|json|jsonc}": [
"biome check --files-ignore-unknown=true --diagnostic-level=error",
Expand Down
4 changes: 2 additions & 2 deletions packages/federation-sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@
"test": "bun test"
},
"dependencies": {
"@rocket.chat/emitter": "^0.31.25",
"@rocket.chat/emitter": "^0.32.0",
"@rocket.chat/federation-core": "workspace:*",
"@rocket.chat/federation-crypto": "workspace:*",
"@rocket.chat/federation-room": "workspace:*",
"mongodb": "^6.16.0",
"reflect-metadata": "^0.2.2",
"tsyringe": "^4.10.0",
"tweetnacl": "^1.0.3",
"zod": "^3.24.1"
"zod": "~4.3.6"
},
"license": "AGPL-3.0",
"author": "Rocket.Chat Technologies Corp. <contact@rocket.chat>",
Expand Down
5 changes: 2 additions & 3 deletions packages/federation-sdk/src/services/config.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import {
toUnpaddedBase64,
} from '@rocket.chat/federation-core';
import { singleton } from 'tsyringe';

import { z } from 'zod';
import * as z from 'zod';

export interface AppConfig {
serverName: string;
Expand Down Expand Up @@ -112,7 +111,7 @@ export class ConfigService {
err: error,
});
throw new Error(
`Invalid configuration: ${error.errors.map((e) => `${e.path.join('.')}: ${e.message}`).join(', ')}`,
`Invalid configuration: ${error.issues.map((e) => `${e.path.join('.')}: ${e.message}`).join(', ')}`,
);
}
throw error;
Expand Down
3 changes: 2 additions & 1 deletion packages/federation-sdk/src/specs/federation-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
EventPduTypeRoomMember,
PduStateEventSchema,
} from '@rocket.chat/federation-room';
import { z } from 'zod';
import * as z from 'zod';

// Common types
export const EventIdSchema = z.string().regex(/^\$[A-Za-z0-9_-]+$/);
Expand Down Expand Up @@ -160,6 +160,7 @@ export const TransactionSchema = z.object({

export const SendTransactionResponseSchema = z.object({
pdus: z.record(
z.string(),
z.object({
error: z.string().optional(),
}),
Expand Down
26 changes: 13 additions & 13 deletions packages/federation-sdk/src/utils/event-schemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ import {
roomIdSchema,
userIdSchema,
} from '@rocket.chat/federation-room';
import { z } from 'zod';
import * as z from 'zod';

const baseEventSchema = z.object({
type: z.string(),
content: z.record(z.any()).or(z.object({})),
content: z.record(z.string(), z.any()).or(z.object({})),
sender: userIdSchema,
room_id: roomIdSchema,
origin_server_ts: z.number().int().positive(),
Expand All @@ -21,8 +21,8 @@ const baseEventSchema = z.object({
.array(z.string().or(z.tuple([z.string(), z.string()])))
.optional(),
redacts: eventIdSchema.optional(),
hashes: z.record(z.string()).optional(),
signatures: z.record(z.record(z.string())).optional(),
hashes: z.record(z.string(), z.string()).optional(),
signatures: z.record(z.string(), z.record(z.string(), z.string())).optional(),
unsigned: z.any().optional(),
});

Expand All @@ -34,7 +34,7 @@ const createEventSchema = baseEventSchema.extend({
room_version: z.string(),
creator: userIdSchema,
})
.and(z.record(z.any())),
.and(z.record(z.string(), z.any())),
prev_events: z.array(z.any()).max(0).optional(),
auth_events: z.array(z.any()).max(0).optional(),
});
Expand All @@ -48,7 +48,7 @@ const memberEventSchema = baseEventSchema.extend({
displayname: z.string().optional().nullable(),
avatar_url: z.string().optional().nullable(),
})
.and(z.record(z.any())),
.and(z.record(z.string(), z.any())),
});

const messageEventSchema = baseEventSchema.extend({
Expand All @@ -58,7 +58,7 @@ const messageEventSchema = baseEventSchema.extend({
msgtype: z.string(),
body: z.string(),
})
.and(z.record(z.any())),
.and(z.record(z.string(), z.any())),
});

const reactionEventSchema = baseEventSchema.extend({
Expand All @@ -71,7 +71,7 @@ const reactionEventSchema = baseEventSchema.extend({
key: z.string(),
}),
})
.and(z.record(z.any())),
.and(z.record(z.string(), z.any())),
});

const powerLevelsEventSchema = baseEventSchema.extend({
Expand All @@ -83,13 +83,13 @@ const powerLevelsEventSchema = baseEventSchema.extend({
kick: z.number().int().default(50),
redact: z.number().int().default(50),
invite: z.number().int().default(50),
events: z.record(z.number().int()).optional(),
events: z.record(z.string(), z.number().int()).optional(),
events_default: z.number().int().default(0),
state_default: z.number().int().default(50),
users: z.record(z.number().int()).optional(),
users: z.record(z.string(), z.number().int()).optional(),
users_default: z.number().int().default(0),
})
.and(z.record(z.any())),
.and(z.record(z.string(), z.any())),
});

const joinRulesEventSchema = baseEventSchema.extend({
Expand All @@ -99,7 +99,7 @@ const joinRulesEventSchema = baseEventSchema.extend({
.object({
join_rule: z.enum(['public', 'knock', 'invite', 'private']),
})
.and(z.record(z.any())),
.and(z.record(z.string(), z.any())),
});

const redactionEventSchema = baseEventSchema.extend({
Expand All @@ -109,7 +109,7 @@ const redactionEventSchema = baseEventSchema.extend({
.object({
reason: z.string().optional(),
})
.and(z.record(z.any())),
.and(z.record(z.string(), z.any())),
});

const roomV10Schemas = {
Expand Down
2 changes: 1 addition & 1 deletion packages/homeserver/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"@rocket.chat/federation-core": "workspace:*",
"@rocket.chat/federation-sdk": "workspace:*",
"@rocket.chat/federation-room": "workspace:*",
"@rocket.chat/emitter": "^0.31.25",
"@rocket.chat/emitter": "^0.32.0",
"elysia": "^1.1.26",
"mongodb": "^6.16.0",
"tsyringe": "^4.10.0"
Expand Down
2 changes: 1 addition & 1 deletion packages/room/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"dependencies": {
"@datastructures-js/priority-queue": "^6.3.5",
"@rocket.chat/federation-crypto": "workspace:*",
"zod": "^3.24.1"
"zod": "~4.3.6"
},
"devDependencies": {
"bun-types": "latest"
Expand Down
3 changes: 2 additions & 1 deletion packages/room/src/types/_common.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import z from 'zod';
import * as z from 'zod';

import type { Pdu, PduType } from './v3-11';

export type StateKey = string;
Expand Down
2 changes: 1 addition & 1 deletion packages/room/src/types/v3-11.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { z } from 'zod';
import * as z from 'zod';
import {
PduForType,
eventIdSchema,
Expand Down