snapshot of https://github.com/RocketChat/Rocket.Chat.git (develop, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Create issues from TODOs / todos (push) Failing after 3s
Close inactive issues / close-issues (push) Has been cancelled
Deploy GitHub Pages / deploy-preview (push) Has been cancelled
CI / ⚙️ Variables Setup (push) Has been cancelled
CI / ⚙️ Test Guard (push) Has been cancelled
CI / 🚀 Notify external services - draft (push) Has been cancelled
CI / 📦 Build Packages (push) Has been cancelled
CI / 📦 Meteor Build (coverage) (push) Has been cancelled
CI / 📦 Meteor Build (production) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [account-service presence-service omnichannel-transcript-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [authorization-service queue-worker-service ddp-streamer-service], fips) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Build Docker (amd64, [rocketchat], fips) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [account-service presence-service omnichannel-transcript-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [authorization-service queue-worker-service ddp-streamer-service], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], ${{ (github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production' }}) (push) Has been cancelled
CI / 🚢 Build Docker (arm64, [rocketchat], coverage) (push) Has been cancelled
CI / 🚢 Publish Docker Images (ghcr.io) (push) Has been cancelled
CI / 📦 Track Image Sizes (push) Has been cancelled
CI / 🔎 Code Check - Action Lint (push) Has been cancelled
CI / 🔎 Code Check (push) Has been cancelled
CI / 🔨 Test Storybook (push) Has been cancelled
CI / 🔨 Test Unit (push) Has been cancelled
CI / 🔨 Test API (CE) (push) Has been cancelled
CI / 🔨 Test API Livechat (CE) (push) Has been cancelled
CI / 🔨 Test UI (CE) (push) Has been cancelled
CI / 🔨 Test API (EE) (push) Has been cancelled
CI / 🔨 Test API Livechat (EE) (push) Has been cancelled
CI / 🔨 Test API Apps (deno-runtime - EE) (push) Has been cancelled
CI / 🔨 Test UI (EE) (push) Has been cancelled
CI / 🔨 Test API (FIPS) (push) Has been cancelled
CI / 🔨 Test API Livechat (FIPS) (push) Has been cancelled
CI / 🔨 Test UI (FIPS) (push) Has been cancelled
CI / 🔨 Test Federation Matrix (push) Has been cancelled
CI / 📊 Report Coverage (push) Has been cancelled
CI / ✅ Tests Done (push) Has been cancelled
CI / 🚀 Publish build assets (push) Has been cancelled
CI / 🚀 Publish Docker Images (DockerHub) (push) Has been cancelled
CI / 🚀 Notify external services (push) Has been cancelled
CI / Update Version Durability (push) Has been cancelled
Release / Release (push) Has been cancelled
Auto-close duplicate issues / auto-close-duplicates (push) Failing after 1s
Code scanning - action / CodeQL-Build (push) Failing after 1s

This commit is contained in:
upstream-mirror
2026-09-16 01:21:02 +05:00
commit 30810eecd7
10161 changed files with 987110 additions and 0 deletions

8
.changeset/README.md Normal file
View File

@@ -0,0 +1,8 @@
# Changesets
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)

View File

@@ -0,0 +1,7 @@
---
'@rocket.chat/media-signaling': minor
'@rocket.chat/media-calls': minor
'@rocket.chat/ui-voip': minor
---
Improves the logic of when the Busy Tone should be played after a call ends

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Fixes the Docker image crashing at boot on arm64 with `Error loading shared library ld-linux-aarch64.so.1` while loading `argon2.node`. The Meteor bundle carries `build/Release` output compiled on the glibc-based CI host, and `node-gyp-build` prefers it over the musl binaries shipped under `prebuilds/` in the same package, so the wrong one was selected at runtime.

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Fixes auto-translate continuing to translate messages with the previously selected service provider after switching providers, until the server was restarted or the feature was disabled and re-enabled.

14
.changeset/config.json Normal file
View File

@@ -0,0 +1,14 @@
{
"$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json",
"changelog": ["@rocket.chat/release-changelog", { "repo": "RocketChat/Rocket.Chat" }],
"commit": false,
"fixed": [["@rocket.chat/meteor", "@rocket.chat/core-typings", "@rocket.chat/rest-typings"]],
"linked": [],
"access": "public",
"baseBranch": "develop",
"updateInternalDependencies": "patch",
"ignore": [],
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
"onlyUpdatePeerDependentsWhenOutOfRange": true
}
}

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/css-supports': patch
---
Moved `@rocket.chat/css-supports` into the Rocket.Chat monorepo, continuing from the frozen Fuselage 0.31.25 release. The memoized, SSR-safe `CSS.supports` facade keeps the same API and runtime behaviour; only its build, lint and test wiring changed, none of which is published.

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Fixes the custom emoji picker returning zero emoji on workspaces running with `ALLOW_UNSAFE_QUERY_AND_FIELDS_API_PARAMS=true`, caused by the client sending an empty `query` string to `emoji-custom.list`

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Deprecates the `getRoomJoinCode` real-time API method. It has had no caller since the room settings panel stopped revealing join codes, and will be removed in 9.0.0 without a replacement.

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Deprecates the `raix:push-setuser` real-time API method. It was inherited from the `raix:push` package for Cordova clients and has never been called by Rocket.Chat clients, which bind push tokens to users through `POST /v1/push.token`. It will be removed in 9.0.0 without a replacement.

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Deprecates the `getMessages` real-time API method in favor of the new `POST /v1/chat.getMessages` endpoint. The method keeps working until it is removed in 9.0.0.

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Deprecates the `loadHistory` and `loadNextMessages` real-time API methods in favor of the new `GET /v1/rooms.history` endpoint. Both methods keep working until they are removed in 9.0.0.

View File

@@ -0,0 +1,6 @@
---
'@rocket.chat/meteor': patch
'@rocket.chat/ui-client': patch
---
Migrates the setup wizard off the `getSetupWizardParameters`, `cloud:getWorkspaceRegisterData` and `registerUser` real-time API methods, in favor of `GET /v1/setupWizard.parameters`, `GET /v1/cloud.workspaceRegisterData` and `POST /v1/users.register`. The first two methods are now deprecated and keep working until they are removed in 9.0.0.

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Deprecates the `loadSurroundingMessages` real-time API method in favor of the `aroundId` parameter of `GET /v1/rooms.history`. The method keeps working until it is removed in 9.0.0.

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': minor
---
Deprecates the Gravatar integration. Default avatars fetched from Gravatar on user creation and Gravatar-based avatar suggestions in the profile settings will be removed in a future major release; a warning is now logged when they are used.

View File

@@ -0,0 +1,7 @@
---
'@rocket.chat/model-typings': patch
'@rocket.chat/models': patch
'@rocket.chat/meteor': patch
---
Fixes the admin and search directory omitting local users whose documents still carried data from the removed legacy federation, making them unsearchable in Directory > Users while still visible in Spotlight and Administration > Users.

View File

@@ -0,0 +1,12 @@
---
'@rocket.chat/media-calls': minor
'@rocket.chat/model-typings': minor
'@rocket.chat/ui-voip': minor
'@rocket.chat/models': minor
'@rocket.chat/i18n': minor
'@rocket.chat/core-typings': minor
'@rocket.chat/rest-typings': minor
'@rocket.chat/meteor': minor
---
Adds name and avatar resolution for external voice calls

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Fixes an issue where message attachments lose their collapsed state when scrolled out of view.

View File

@@ -0,0 +1,15 @@
---
'@rocket.chat/federation-matrix': patch
'@rocket.chat/meteor': patch
---
Fixes federation endpoints rejecting requests that are valid per the Matrix specification:
- `publicRooms` (GET and POST) required params/fields the spec marks optional
- `query/profile` rejected spec-valid profile fields such as `m.tz`
- `get_missing_events` required the optional `limit` field and bounded it
- `make_join` returned 500 instead of 400 `M_INCOMPATIBLE_ROOM_VERSION` for unsupported room versions
- `backfill` rejected spec-valid `limit` values
- `send` rejected an entire transaction when a single PDU didn't match a fixed event shape, instead of reporting failures per PDU
Also links every federation endpoint to its definition in the Matrix specification.

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': minor
---
Improves draft handling by discarding the stored draft as soon as a message is sent, instead of keeping it until the room is changed

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Fixes long custom statuses being cut off without an ellipsis in the user status menu.

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': minor
---
Improves the sidebar to keep the room currently open listed under its category even while that category is collapsed, so it stays clear which room is being viewed

5
.changeset/meteor-3-5.md Normal file
View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Update Meteor to 3.5.2 and bump Node.js to 24.15.0 to match the new bundled runtime. Also bumps `isolated-vm` to 6.2.0 for Node.js 24 compatibility.

View File

@@ -0,0 +1,6 @@
---
"@rocket.chat/meteor": patch
"@rocket.chat/web-ui-registration": patch
---
Improves the mobile web experience: the page background now follows the active theme so Safari no longer shows white strips in the overscroll/safe-area regions (and tints its toolbar) in dark mode; the login "Welcome to <workspace>" title is scaled down on small screens; focusing a field no longer triggers iOS Safari's auto zoom-in (inputs use a 16px minimum on mobile); the login email/username field no longer auto-capitalizes/auto-corrects; and the connection status bar layout no longer truncates its "Connect" button on narrow screens.

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Fixes empty notifications when video conferences are created

View File

@@ -0,0 +1,8 @@
---
'@rocket.chat/core-typings': minor
'@rocket.chat/rest-typings': minor
'@rocket.chat/i18n': minor
'@rocket.chat/meteor': minor
---
Introduces custom, user-defined categories to the sidebar (Enterprise only). Users can create, rename, delete and reorder categories (menu-driven), and move rooms into them via the room context menu or the room header.

View File

@@ -0,0 +1,9 @@
---
'@rocket.chat/random': patch
'@rocket.chat/i18n': patch
'@rocket.chat/license': patch
'@rocket.chat/ui-client': patch
'@rocket.chat/meteor': patch
---
Improves performance of several hot code paths without changing behavior: generates random IDs with a single `crypto.randomBytes` call instead of one per character, caches constant regular expressions used by the markdown/mention/autotranslate parsers instead of recompiling them for every message, skips the channel-mention database query for messages without channel mentions, deduplicates the room member count query when a message contains both `@all` and `@here`, and replaces linear array scans and spread-accumulators with Map/Set lookups in API response shaping (files, DM members, directory search and team listing).

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Fixes users not being added to the default channels (such as `#general`) when they are assigned their first username, which affected the admin created by the setup wizard on a brand new workspace and OAuth, SAML and LDAP users that pick a username through the "Register Username" screen.

View File

@@ -0,0 +1,10 @@
---
'@rocket.chat/media-calls': minor
'@rocket.chat/model-typings': minor
'@rocket.chat/core-typings': minor
'@rocket.chat/models': minor
'@rocket.chat/meteor': minor
---
Started storing SIP Call Id on the media calls model
Added an endpoint to retrieve media calls data

View File

@@ -0,0 +1,6 @@
---
'@rocket.chat/rest-typings': minor
'@rocket.chat/meteor': minor
---
Adds a new `POST /v1/chat.getMessages` endpoint to fetch several messages at once by id, including messages from different rooms. The request fails if any of the messages belongs to a room the caller cannot read.

View File

@@ -0,0 +1,6 @@
---
'@rocket.chat/rest-typings': minor
'@rocket.chat/meteor': minor
---
Adds a new `GET /v1/cloud.workspaceRegisterData` endpoint returning the base64 encoded workspace registration payload used by the offline cloud registration flow. It requires the `manage-cloud` permission.

View File

@@ -0,0 +1,6 @@
---
'@rocket.chat/rest-typings': minor
'@rocket.chat/meteor': minor
---
Adds an `aroundId` parameter to `GET /v1/rooms.history`, returning a window of messages centered on a given message instead of a page from one end of the room. This is what jumping to a quoted message, a search result or a thread message uses to load the surrounding conversation.

View File

@@ -0,0 +1,6 @@
---
'@rocket.chat/rest-typings': minor
'@rocket.chat/meteor': minor
---
Adds a new `GET /v1/rooms.history` endpoint to load a room's message history. Unlike the existing `channels.history`, `groups.history`, `im.history` and `dm.history` endpoints, it works with any room type through a single route, and can be used to read public channels anonymously when `Accounts_AllowAnonymousRead` is enabled.

View File

@@ -0,0 +1,6 @@
---
'@rocket.chat/rest-typings': minor
'@rocket.chat/meteor': minor
---
Adds a new `GET /v1/setupWizard.parameters` endpoint returning the settings flagged for the setup wizard along with a `serverAlreadyRegistered` flag.

View File

@@ -0,0 +1,9 @@
---
'@rocket.chat/meteor': minor
'@rocket.chat/ui-client': minor
'@rocket.chat/i18n': minor
---
Adds a configurable **Room Toolbox Layout**, available as an opt-in **Feature Preview** (My Account → Feature Preview → Room → **Room Toolbox Layout**). While the feature preview is off, the room header toolbox keeps its current behavior and the setting has no effect.
Admins can define the layout through the new workspace setting **Room Toolbox Layout** (`Room_Toolbox_Layout`) under **Admin → Settings → Layout → Room Header**, which is itself only shown when **Feature Preview** is enabled for the workspace. The setting value is validated against a JSON schema when saved, so a malformed configuration is rejected with an error instead of being silently ignored

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Shows the loading skeleton instead of flashing the login form while a stored session is being resumed

View File

@@ -0,0 +1,6 @@
---
'@rocket.chat/core-typings': patch
'@rocket.chat/meteor': patch
---
Fixes the removed `Drafts` sidebar group reappearing as an empty category on workspaces upgraded from a build that shipped it

View File

@@ -0,0 +1,7 @@
---
'@rocket.chat/storybook-dark-mode': minor
---
Declares `storybook` as a peer dependency, at `^9.0.0`. The addon has always imported from `storybook/preview-api`, `storybook/manager-api`, `storybook/theming` and several `storybook/internal/*` paths, but never said so, which left the requirement implicit and the internal APIs it relies on without a version contract.
Also stops shipping `.d.ts` and `.d.ts.map` files inside `dist/esm` and `dist/cjs`. Declarations were being emitted three times over and only the `dist/ts` copy is referenced by `types`, so the other two were dead weight in the tarball. Anything deep-importing types from `dist/esm` or `dist/cjs` — as opposed to resolving them through the package entry point — needs to use `dist/ts` instead.

View File

@@ -0,0 +1,5 @@
---
"@rocket.chat/meteor": patch
---
Fixes 'mark as unread' action not available for federated messages

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Aligns the rate limits of `spotlight`, `directory`, `chat.followMessage` and `chat.unfollowMessage` with the values defined in the DDP methods they replaced. They were falling back to the generic REST default of 10 requests per 60 seconds instead.

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Fixes team deletion failing when the team's main room no longer exists. Such teams were left orphaned: hidden from the admin UI, still reserving their name, and impossible to remove through any supported path. Deleting a team now completes even when its main room is already gone, so a deletion interrupted midway can be finished by simply retrying it, and the team name becomes available again.

View File

@@ -0,0 +1,7 @@
---
'@rocket.chat/meteor': patch
'@rocket.chat/models': patch
'@rocket.chat/model-typings': patch
---
Fixes Omnichannel rooms failing to register agent responses (and showing send errors on messages and file uploads that were actually delivered) when the room carried corrupted visitor activity data created by older app integrations

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Ensures the message composer is cleared after a slash command is executed.

View File

@@ -0,0 +1,6 @@
---
'@rocket.chat/ui-voip': minor
'@rocket.chat/meteor': patch
---
Improved the in-call voice widget: media elements no longer detach and re-attach when an unrelated device changes, so a shared screen or camera stops blinking whenever the microphone is muted or a device is switched.

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Fixes ignored messages from ignored users in threads.

View File

@@ -0,0 +1,5 @@
---
'@rocket.chat/meteor': patch
---
Fixes direct messages addressed by username, such as the ones opened with **Reply in direct message**, not being found on the first lookup — which made opening a conversation cost an extra request and log an avoidable `Invalid Room` error.

41
.devcontainer/Dockerfile Normal file
View File

@@ -0,0 +1,41 @@
FROM mcr.microsoft.com/vscode/devcontainers/base:ubuntu
COPY package.json /tmp/package.json
RUN apt-get update && apt-get install -y \
apt-transport-https \
build-essential \
ca-certificates \
curl \
jq \
libssl-dev && \
rm -rf /var/lib/apt/lists/*
ENV NVM_DIR /usr/local/nvm
RUN mkdir -p $NVM_DIR && \
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash && \
bash -c ". $NVM_DIR/nvm.sh && nvm install $(jq -r '.engines.node' /tmp/package.json) && npm install -g yarn"
RUN echo "export NVM_DIR=$NVM_DIR" >> /etc/bash.bashrc && \
echo "[ -s \"$NVM_DIR/nvm.sh\" ] && \. \"$NVM_DIR/nvm.sh\"" >> /etc/bash.bashrc
ENV DENO_INSTALL=/usr/local/deno
RUN mkdir -p $DENO_INSTALL && \
curl -fsSL https://deno.land/install.sh | sh
ENV DENO_INSTALL="/usr/local/deno"
ENV PATH="$DENO_INSTALL/bin:$PATH"
RUN echo 'export DENO_INSTALL="/usr/local/deno"' >> /etc/bash.bashrc && \
echo 'export PATH="$DENO_INSTALL/bin:$PATH"' >> /etc/bash.bashrc
ENV METEOR_INSTALL="/usr/local/meteor"
ENV PATH="$METEOR_INSTALL/bin:$PATH"
RUN curl https://install.meteor.com/ | sh && \
mv ~/.meteor $METEOR_INSTALL
RUN echo 'export METEOR_INSTALL="/usr/local/meteor"' >> /etc/bash.bashrc && \
echo 'export PATH="$METEOR_INSTALL/bin:$PATH"' >> /etc/bash.bashrc
CMD ["bash"]

View File

@@ -0,0 +1,18 @@
{
"name": "Rocket.Chat Gitpod",
"build": {
"context": "..",
"dockerfile": "./Dockerfile"
},
"features": {
"ghcr.io/devcontainers/features/docker-in-docker:2": {}
},
"forwardPorts": [3000],
"customizations": {
"vscode": {
"extensions": [
"esbenp.prettier-vscode"
]
}
}
}

19
.editorconfig Normal file
View File

@@ -0,0 +1,19 @@
# EditorConfig is awesome: http://EditorConfig.org
root = true
[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.{js,coffee,html,less,css,json}]
indent_style = tab
[*.i18n.json]
indent_style = space
indent_size = 2
[*.md]
trim_trailing_whitespace = false

42
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1,42 @@
/packages/* @RocketChat/Architecture
/packages/apps-engine/ @RocketChat/apps
/packages/apps/ @RocketChat/apps
/packages/core-typings/ @RocketChat/Architecture
/packages/rest-typings/ @RocketChat/Architecture @RocketChat/backend
/packages/ui-contexts/ @RocketChat/frontend
/packages/eslint-config/ @RocketChat/Architecture
/packages/livechat/ @RocketChat/frontend @RocketChat/Architecture
/.vscode/ @RocketChat/Architecture
/.github/ @RocketChat/Architecture
/_templates/ @RocketChat/Architecture
/apps/meteor/client/ @RocketChat/frontend
/apps/meteor/tests/e2e @RocketChat/frontend
/apps/meteor/tests/end-to-end @RocketChat/backend
/apps/meteor/tests/unit/app @RocketChat/backend
/apps/meteor/tests/unit/client @RocketChat/frontend
/apps/meteor/tests/unit/server @RocketChat/backend
/apps/meteor/app/apps/ @RocketChat/apps
/apps/meteor/app/livechat @RocketChat/omnichannel
/apps/meteor/app/file-upload @RocketChat/backend
/apps/meteor/app/integrations @RocketChat/backend
/apps/meteor/server @RocketChat/backend
/apps/meteor/server/lib/omnichannel @RocketChat/omnichannel
/apps/meteor/server/hooks/omnichannel @RocketChat/omnichannel
/apps/meteor/server/api/v1/omnichannel @RocketChat/omnichannel
/apps/meteor/server/meteor-methods/omnichannel @RocketChat/omnichannel
/packages/models @RocketChat/Architecture
apps/meteor/server/startup/migrations @RocketChat/Architecture
/apps/meteor/packages/rocketchat-livechat @RocketChat/omnichannel
/apps/meteor/server/features/EmailInbox @RocketChat/omnichannel
/apps/meteor/ee/server/apps/ @RocketChat/apps
/apps/meteor/ee/tests/unit/server/apps/ @RocketChat/apps
/apps/meteor/ee/server/lib/canned-responses @RocketChat/omnichannel
/apps/meteor/ee/server/hooks/canned-responses @RocketChat/omnichannel
/apps/meteor/ee/server/api/v1/canned-responses.ts @RocketChat/omnichannel
/apps/meteor/ee/server/lib/omnichannel @RocketChat/omnichannel
/apps/meteor/ee/server/hooks/omnichannel @RocketChat/omnichannel
/apps/meteor/ee/server/api/v1/omnichannel @RocketChat/omnichannel
/apps/meteor/ee/server/meteor-methods/saveCannedResponse.ts @RocketChat/omnichannel
/apps/meteor/ee/server/meteor-methods/removeCannedResponse.ts @RocketChat/omnichannel
/apps/meteor/client/omnichannel @RocketChat/omnichannel
/apps/meteor/client/components/omnichannel @RocketChat/omnichannel

27
.github/CONTRIBUTING.md vendored Normal file
View File

@@ -0,0 +1,27 @@
# Contributing to Rocket.Chat
**First off, thanks for taking the time to contribute! :tada::+1:**
> There are many ways to contribute to Rocket.Chat even if you're not technical or a developer:
>
> * Email us at marketing@rocket.chat to tell us how much you love the project
> * Write about us in your blogs
> * Fix some small typos in our [documentation](https://docs.rocket.chat/contributing)
> * Become our [GitHub sponsor](https://github.com/sponsors/RocketChat)
> * Tell others about us and help us spread the word
>
> Every bit of contribution is appreciated 🙂 thank you!
The following is a set of guidelines for contributing to Rocket.Chat, which are hosted in the [Rocket.Chat Organization](https://github.com/RocketChat) on GitHub.
__Note:__ If there's a feature you'd like, there's a bug you'd like to fix, or you'd just like to get involved please raise an issue and start a conversation. We'll help as much as we can so you can get contributing - although we may not always be able to respond right away :)
## Development Guidelines
Check out our Handbook for the [Development Guidelines](https://handbook.rocket.chat/space/RnD/359891343/%F0%9F%8C%90+Development+Guidelines) on how to set up your environment, do code, test and push your code. There you find our patterns on how to compose your Pull Requests' titles to have your contribution accepted.
## Contributor License Agreement
To have your contribution accepted you must sign our [Contributor License Agreement](https://cla-assistant.io/RocketChat/Rocket.Chat). In case you submit a Pull Request before signing the CLA GitHub will alert you with a new comment asking you to sign and will block the Pull Request from being merged by us.
Please review and sign our CLA at https://cla-assistant.io/RocketChat/Rocket.Chat

59
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,59 @@
---
name: Bug report
about: Create a report to help us improve
---
<!--
Please see our guide for opening issues: https://developer.rocket.chat/rocket.chat/contribute-to-rocket.chat/ways-to-contribute/report-bugs
If you have questions or are looking for help/support please see: https://rocket.chat/docs/getting-support
If you are experiencing a bug please search our issues to be sure it is not already present: https://github.com/RocketChat/Rocket.Chat/issues
-->
### Description:
<!-- A clear and concise description of what the bug is. -->
### Steps to reproduce:
1. <!-- Go to '...' -->
2. <!-- Click on '....' -->
3. <!-- and so on... -->
### Expected behavior:
<!-- What you expect to happen -->
### Actual behavior:
<!-- What actually happens with SCREENSHOT, if applicable -->
### Server Setup Information:
- Version of Rocket.Chat Server:
- License Type:
- Number of Users:
- Operating System:
- Deployment Method: <!-- snap/docker/tar/etc -->
- Number of Running Instances:
- DB Replicaset Oplog:
- NodeJS Version:
- MongoDB Version:
### Client Setup Information
- Desktop App or Browser Version:
- Operating System:
### Additional context
<!-- Add any other context about the problem here. -->
### Relevant logs:
<!-- Logs from both SERVER and BROWSER -->
<!-- For more information about collecting logs please see: https://rocket.chat/docs/contributing/reporting-issues#gathering-logs -->

59
.github/ISSUE_TEMPLATE/release.md vendored Normal file
View File

@@ -0,0 +1,59 @@
---
name: Release
about: Internal release checklist template
---
# Release {version}
We are releasing a new version, this issue will keep track of the progress between the first release candidate (20th of each month) to the final release (27th of each month).
Beginning on the 20th of each month, we will start the release process which ends 7 days later (the 27th). During this period of time, we will enter a "Feature Freeze". This Feature Freeze means that we will only be merging pull requests which fix bugs and not ones that add new features.
When you find a bug that is a regression, please open a new issue and link it to this one.
## Before Release - Preparation - 1 business day before the day 20th
- [x] Create the issue to track the release progress
- [ ] Define the highlights from release PRs as a suggestion to be included on Blog Post <!-- link to the website's issue -->
- [ ] Talk to the Marketing Team about starting the release Blog Post
- [ ] Talk to the Documentation Team about ensuring the Docs are up to date and all pull requests are merged
- [ ] Sync translations from [LingoHub](https://translate.lingohub.com/rocketchat/rocket-dot-chat/dashboard)
## Release Candidate 1 - On the 20th
- [ ] Execute action `Release Candidate` via [Houston CLI](https://github.com/RocketChat/Rocket.Chat.Houston) (`houston release`)
- [ ] Check if `release-candidate` branch was published
- [ ] Check if the tag was published and contains the history
- [ ] Ensure the build is passing on [CircleCI](https://circleci.com/gh/RocketChat/Rocket.Chat)
- [ ] Ensure the image was sent to [Docker Hub](https://hub.docker.com/r/rocketchat/rocket.chat/tags/)
<!-- Copy following block for next release candidates
## Release Candidate {release-candidate-version} - On the {day}
- [ ] Execute action `Release Candidate` via [Houston CLI](https://github.com/RocketChat/Rocket.Chat.Houston) (`houston release`)
- [ ] Check if `release-candidate` branch was published
- [ ] Check if the tag was published and contains the history
- [ ] Ensure the build is passing on [CircleCI](https://circleci.com/gh/RocketChat/Rocket.Chat)
- [ ] Ensure the image was sent to [Docker Hub](https://hub.docker.com/r/rocketchat/rocket.chat/tags/)
-->
## Final Release - On the 27th
- [ ] Execute action `Final Release` via [Houston CLI](https://github.com/RocketChat/Rocket.Chat.Houston) (`houston release`)
- [ ] Check if `release-{version}` branch was published
- [ ] Check if the release was created as **draft** and contains the history
- [ ] Check if the release Pull Request was created and contains the history
- [ ] Ensure the **Pull Request** build is passing on [CircleCI](https://circleci.com/gh/RocketChat/Rocket.Chat)
- [ ] When the build is passing ask for Pull Request approval
- [ ] When approved, merge it!
- [ ] Ensure the **Tag** build is passing on [CircleCI](https://circleci.com/gh/RocketChat/Rocket.Chat)
- [ ] Ensure the image was sent to [Docker Hub](https://hub.docker.com/r/rocketchat/rocket.chat/tags/)
- [ ] After all edit the release/tag and publish it
## After Release - Conclusion - 1 business day after the 27th
- [ ] Ensure all of the related issues were closed
- [ ] Determine if all of the related issues were correctly assigned to this version's milestone
- [ ] Get an update from Marketing Team about the release of Blog Post
- [ ] Check with the Documentation Team about the Docs release
- [ ] Sync develop
- [ ] Execute action `Develop Sync` via [Houston CLI](https://github.com/RocketChat/Rocket.Chat.Houston) (`houston release`)
- [ ] Ensure the **Pull Request** build is passing on [CircleCI](https://circleci.com/gh/RocketChat/Rocket.Chat)
- [ ] When the build has passed, ask for approval and wait
- [ ] Merge Sync PR

39
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,39 @@
<!-- This is a pull request template, you do not need to uncomment or remove the comments, they won't show up in the PR text. -->
<!-- Your Pull Request name should start with one of the following tags
feat: Adding a new feature
refactor: A code change that doesn't change behavior (it doesn't add anything and doesn't fix anything)
fix: For bug fixes that affect the end-user
chore: For small tasks
docs: For documentation
ci: For updating CI configuration
test: For adding tests
i18n: For updating any translations
regression: Issues created/reported/fixed during the development phase. kind of problem that never existed in production and that we don't need to list in a changelog for the end user
-->
<!-- Checklist!!! If you're unsure about any of them, don't hesitate to ask. We're here to help! This is simply a reminder of what we are going to look for before merging your code.
- I have read the Contributing Guide - https://github.com/RocketChat/Rocket.Chat/blob/develop/.github/CONTRIBUTING.md#contributing-to-rocketchat doc
- I have signed the CLA - https://cla-assistant.io/RocketChat/Rocket.Chat
- Lint and unit tests pass locally with my changes
- I have added tests that prove my fix is effective or that my feature works (if applicable)
- I have added necessary documentation (if applicable)
- Any dependent changes have been merged and published in downstream modules
-->
## Proposed changes (including videos or screenshots)
<!--
Describe the big picture of your changes here to communicate to the maintainers why we should accept this pull request.
If it fixes a bug or resolves a feature request, be sure to link to that issue below.
This description won't be displayed to our end users in the release notes, so feel free to add as much technical context as needed.
If the changes introduced in this pull request must be presented in the release notes, make sure to add a changeset file. Check our guidelines for adding a changeset to your pull request: https://developer.rocket.chat/contribute-to-rocket.chat/modes-of-contribution/participate-in-rocket.chat-development/development-workflow#4.-adding-changeset-to-your-pull-request
-->
## Issue(s)
<!-- Link the issues being closed by or related to this PR. For example, you can use #594 if this PR closes issue number 594 -->
## Steps to test or reproduce
<!-- Mention how you would reproduce the bug if not mentioned on the issue page already. Also mention which screens are going to have the changes if applicable -->
## Further comments
<!-- If this is a relatively large or complex change, kick off the discussion by explaining why you chose the solution you did and what alternatives you considered, etc... -->

17
.github/actionlint-matcher.json vendored Normal file
View File

@@ -0,0 +1,17 @@
{
"problemMatcher": [
{
"owner": "actionlint",
"pattern": [
{
"regexp": "^(?:\\x1b\\[\\d+m)?(.+?)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*:(?:\\x1b\\[\\d+m)*(\\d+)(?:\\x1b\\[\\d+m)*: (?:\\x1b\\[\\d+m)*(.+?)(?:\\x1b\\[\\d+m)* \\[(.+?)\\]$",
"file": 1,
"line": 2,
"column": 3,
"message": 4,
"code": 5
}
]
}
]
}

3
.github/actionlint.yaml vendored Normal file
View File

@@ -0,0 +1,3 @@
paths:
.github/workflows/**/*.yml:
ignore: ['file "dist/index\.js" does not exist in .*/packages/release-action']

246
.github/actions/build-docker/action.yml vendored Normal file
View File

@@ -0,0 +1,246 @@
name: 'Build Docker'
description: 'Build Docker images for Rocket.Chat and related services'
inputs:
CR_USER:
required: true
description: 'GitHub Container Registry username'
CR_PAT:
required: true
description: 'GitHub Container Registry Personal Access Token'
DOCKER_USER:
required: false
description: 'DockerHub username (required for FIPS builds to pull private base image)'
DOCKER_PASS:
required: false
description: 'DockerHub password (required for FIPS builds to pull private base image)'
deno-version:
required: true
description: 'Deno version'
arch:
required: false
description: 'Architecture'
default: 'arm64'
service:
required: false
description: 'Container to build'
publish-image:
required: false
description: 'Publish image'
default: 'true'
setup-docker:
required: false
description: 'Setup Docker'
default: 'true'
type:
required: false
description: 'production, coverage, or fips'
default: 'coverage'
runs:
using: composite
steps:
- name: Login to GitHub Container Registry
if: inputs.publish-image == 'true' && github.actor != 'dependabot[bot]' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop')
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
registry: ghcr.io
username: ${{ inputs.CR_USER }}
password: ${{ inputs.CR_PAT }}
- name: Login to DockerHub
# FIPS base image (rocketchat/dhi-node) lives in a private DockerHub repo and requires auth to pull.
if: inputs.type == 'fips' && (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.event_name == 'merge_group' || github.ref == 'refs/heads/develop')
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
with:
username: ${{ inputs.DOCKER_USER }}
password: ${{ inputs.DOCKER_PASS }}
- name: Restore meteor build
if: inputs.service == 'rocketchat'
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: build-${{ inputs.type == 'fips' && ((github.event_name != 'release' && github.ref != 'refs/heads/develop') && 'coverage' || 'production') || inputs.type }}
path: /tmp/build
- name: Unpack meteor build
if: inputs.service == 'rocketchat'
shell: bash
run: |
cd /tmp/build
tar xzf Rocket.Chat.tar.gz
rm Rocket.Chat.tar.gz
- name: Set up Docker
if: inputs.setup-docker == 'true'
uses: docker/setup-docker-action@e43656e248c0bd0647d3f5c195d116aacf6fcaf4 # v4.7.0
with:
daemon-config: |
{
"debug": false,
"features": {
"containerd-snapshotter": true
}
}
# Microservice images build from a pruned, self-contained context (out/<service>)
# produced by `turbo prune`, instead of a hand-maintained list of COPY lines.
# The rocketchat (Meteor) image is a prebuilt bundle and is staged separately above.
- name: Stage service build context
if: inputs.service != 'rocketchat'
shell: bash
env:
INPUT_SERVICE: ${{ inputs.service }}
run: |
set -o xtrace
# The Docker SERVICE arg (folder under ee/apps) lives in the compose build args;
# the compose service name (INPUT_SERVICE) can differ (e.g. ddp-streamer-service).
SERVICE_DIR=$(docker compose -f docker-compose-ci.yml config --format json 2>/dev/null | jq -r --arg s "$INPUT_SERVICE" '.services[$s].build.args.SERVICE')
PKG_NAME=$(node -p "require('./ee/apps/${SERVICE_DIR}/package.json').name")
TURBO_VERSION=$(node -p "require('./package.json').devDependencies.turbo")
rm -rf "out/${SERVICE_DIR}"
# `turbo prune` derives the exact workspace dependency closure for the service — no
# hand-maintained list. --use-gitignore=false also captures the gitignored build output
# we need (dist/, generated definition/), at the cost of dragging in node_modules/.turbo,
# which we strip below; `yarn workspaces focus --production` rebuilds node_modules in-image.
npx -y "turbo@${TURBO_VERSION}" prune "$PKG_NAME" --skip-infer --use-gitignore=false --out-dir "out/${SERVICE_DIR}"
find "out/${SERVICE_DIR}" \( -name node_modules -o -name .turbo \) -type d -prune -exec rm -rf {} +
- name: Build Docker images
shell: bash
env:
DENO_VERSION: ${{ inputs.deno-version }}
INPUT_ARCH: ${{ inputs.arch }}
INPUT_SERVICE: ${{ inputs.service }}
INPUT_PUBLISH_IMAGE: ${{ inputs.publish-image }}
INPUT_TYPE: ${{ inputs.type }}
GITHUB_RUN_ID: ${{ github.run_id }}
GITHUB_SERVER_URL: ${{ github.server_url }}
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_EVENT_NAME: ${{ github.event_name }}
GITHUB_REF: ${{ github.ref }}
run: |
set -o xtrace
compose_fips_override=''
if [[ "$INPUT_TYPE" == 'fips' ]]; then
compose_fips_override='-f docker-compose-ci.fips.yml'
fi
# Removes unnecessary swc cores and sharp binaries to reduce image size
swc_arch='x64'
if [[ "$INPUT_SERVICE" == 'rocketchat' ]]; then
if [[ "$INPUT_ARCH" == 'arm64' ]]; then
swc_arch='arm64'
fi
find /tmp/build/bundle/programs/server/npm/node_modules/@img -type d -name 'sharp-*' -not -name "*-linuxmusl-${swc_arch}" -exec rm -rf {} +
find /tmp/build/bundle/programs/server/npm/node_modules/@napi-rs -type d -name 'pinyin-linux-*' -not -name "*-linux-${swc_arch}-*" -exec rm -rf {} +
find /tmp/build/bundle/programs/server/npm/node_modules/@esbuild -type d -name 'linux-*' -not -name "*-${swc_arch}" -exec rm -rf {} +
find /tmp/build/bundle/programs/server/npm/node_modules/@rocket.chat/apps/node_modules/@esbuild -type d -name 'linux-*' -not -name "*-${swc_arch}" -exec rm -rf {} +
fi
if [[ "$INPUT_PUBLISH_IMAGE" == 'true' ]]; then
LOAD_OR_PUSH="--push"
else
LOAD_OR_PUSH="--load"
fi
# Get image name from docker-compose-ci.yml since rocketchat image is different from service name (rocket.chat)
IMAGE=$(docker compose -f docker-compose-ci.yml $compose_fips_override config --format json 2>/dev/null | jq -r --arg s "$INPUT_SERVICE" '.services[$s].image')
docker buildx bake \
-f docker-compose-ci.yml $compose_fips_override \
${LOAD_OR_PUSH} \
--allow=fs.read=/tmp/build \
--set "*.tags+=${IMAGE}-gha-run-${GITHUB_RUN_ID}" \
--set "*.labels.org.opencontainers.image.description=Build run: ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \
--set "*.labels.org.opencontainers.image.source=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}" \
--set "*.platform=linux/${INPUT_ARCH}" \
--set *.cache-from=type=gha \
--set *.cache-to=type=gha,mode=max \
--provenance=false \
--sbom=false \
--metadata-file "/tmp/meta.json" \
"$INPUT_SERVICE"
echo "Contents of /tmp/meta.json:"
cat /tmp/meta.json
if [[ "$INPUT_PUBLISH_IMAGE" == 'true' ]]; then
SERVICE_SUFFIX=''
if [[ "$INPUT_SERVICE" == 'rocketchat' && "$INPUT_TYPE" == 'coverage' ]] && [[ "$GITHUB_EVENT_NAME" == 'release' || "$GITHUB_REF" == 'refs/heads/develop' ]]; then
SERVICE_SUFFIX='-cov'
elif [[ "$INPUT_TYPE" == 'fips' ]]; then
SERVICE_SUFFIX='-fips'
fi
mkdir -p "/tmp/manifests/${INPUT_SERVICE}${SERVICE_SUFFIX}/${INPUT_ARCH}"
# Get digest and image info
DIGEST=$(jq -r --arg service "$INPUT_SERVICE" '.[$service].["containerimage.digest"]' "/tmp/meta.json")
IMAGE_NO_TAG=$(echo "$IMAGE" | sed 's/:.*$//')
FULL_IMAGE="${IMAGE_NO_TAG}@${DIGEST}"
echo "Inspecting image: $FULL_IMAGE"
# Inspect the image and save complete manifest with sizes (using -v for verbose)
docker manifest inspect -v "$FULL_IMAGE" > "/tmp/manifests/${INPUT_SERVICE}${SERVICE_SUFFIX}/${INPUT_ARCH}/manifest.json"
echo "Saved manifest to /tmp/manifests/${INPUT_SERVICE}${SERVICE_SUFFIX}/${INPUT_ARCH}/manifest.json"
cat "/tmp/manifests/${INPUT_SERVICE}${SERVICE_SUFFIX}/${INPUT_ARCH}/manifest.json" | jq '.'
fi
- name: Save Docker image as artifact
if: inputs.publish-image == 'false' && inputs.arch == 'amd64'
shell: bash
env:
SERVICE: ${{ inputs.service }}
ARCH: ${{ inputs.arch }}
TYPE: ${{ inputs.type }}
run: |
set -o xtrace
compose_fips_override=''
if [[ "$TYPE" == 'fips' ]]; then
compose_fips_override='-f docker-compose-ci.fips.yml'
fi
# Get image name from docker-compose-ci.yml
IMAGE=$(docker compose -f docker-compose-ci.yml $compose_fips_override config --format json 2>/dev/null | jq -r --arg s "$SERVICE" '.services[$s].image')
# Create directory for image archives
mkdir -p /tmp/docker-images
# Save the image to a tar file
docker save "${IMAGE}" -o "/tmp/docker-images/${SERVICE}-${ARCH}-${TYPE}.tar"
echo "Saved image to /tmp/docker-images/${SERVICE}-${ARCH}-${TYPE}.tar"
ls -lh /tmp/docker-images/
- name: Upload Docker image artifact
if: inputs.publish-image == 'false' && inputs.arch == 'amd64'
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: docker-image-${{ inputs.service }}-${{ inputs.arch }}-${{ inputs.type }}
path: /tmp/docker-images/${{ inputs.service }}-${{ inputs.arch }}-${{ inputs.type }}.tar
retention-days: 1
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: inputs.publish-image == 'true'
with:
name: manifests-${{ inputs.service }}-${{ inputs.arch }}-${{ inputs.type }}
path: /tmp/manifests
retention-days: 5
- name: Clean up temporary files
if: inputs.service == 'rocketchat'
shell: bash
run: |
sudo rm -rf /tmp/build

View File

@@ -0,0 +1,581 @@
name: 'Docker Image Size Tracker'
description: 'Track and report Docker image sizes in Pull Requests'
author: 'Rocket.Chat'
inputs:
github-token:
description: 'GitHub token for commenting on PRs'
required: true
ci-pat:
description: 'GitHub token for committing to history branch'
required: true
registry:
description: 'Container registry (e.g., ghcr.io)'
required: false
default: 'ghcr.io'
repository:
description: 'Repository name (e.g., rocketchat)'
required: true
tag:
description: 'Image tag to measure'
required: true
baseline-tag:
description: 'Baseline tag to compare against'
required: false
default: 'develop'
platform:
description: 'Platform architecture to compare (amd64 or arm64)'
required: false
default: 'amd64'
size-thresholds:
description: 'Optional JSON: per-image trigger thresholds. Only comment when an image increase exceeds its threshold. Example: {"rocketchat":{"mb":50,"percent":5},"omnichannel":{"mb":10,"percent":2}}'
required: false
default: ''
fail-thresholds:
description: 'Optional JSON: per-image fail thresholds. Task fails when an image increase exceeds its threshold (mb and/or percent). Example: {"rocketchat":{"mb":100,"percent":15}}'
required: false
default: ''
outputs:
total-size:
description: 'Total size in bytes'
value: ${{ steps.measure.outputs.total-size }}
size-diff:
description: 'Size difference in bytes'
value: ${{ steps.compare.outputs.size-diff }}
size-diff-percent:
description: 'Size difference percentage'
value: ${{ steps.compare.outputs.size-diff-percent }}
comment-triggered:
description: 'Whether to post PR comment (only when size is bigger and thresholds met)'
value: ${{ steps.compare.outputs.comment-triggered }}
failed:
description: 'True if image size exceeded fail-thresholds'
value: ${{ steps.compare.outputs.failed }}
runs:
using: 'composite'
steps:
- name: Download manifests
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
pattern: manifests-*
path: /tmp/manifests
merge-multiple: true
- name: Measure image sizes from artifacts
id: measure
shell: bash
env:
PLATFORM: ${{ inputs.platform }}
TAG: ${{ inputs.tag }}
run: |
echo "Reading image sizes from build artifacts for platform: $PLATFORM"
declare -A sizes
declare -a services_list
total=0
# Loop through service directories (same as publish workflow)
shopt -s nullglob
for service_dir in /tmp/manifests/*; do
[[ -d "$service_dir" ]] || continue
service="$(basename "$service_dir")"
echo "Processing service: $service"
services_list+=("$service")
size=0
# Read only the specified platform architecture
manifest_file="$service_dir/$PLATFORM/manifest.json"
if [[ -f "$manifest_file" ]]; then
# docker manifest inspect -v puts the manifest under SchemaV2Manifest
# (Docker schema2 images) or OCIManifest (OCI images, which buildx
# produces by default). Coalesce so both formats are read.
config_size=$(jq -r '(.SchemaV2Manifest // .OCIManifest).config.size // 0' "$manifest_file")
layers_size=$(jq '[(.SchemaV2Manifest // .OCIManifest).layers[]?.size // 0] | add // 0' "$manifest_file")
size=$((config_size + layers_size))
echo " → Found $manifest_file: $size bytes (config: $config_size, layers: $layers_size)"
else
echo " ⚠ Manifest not found for platform $PLATFORM: $manifest_file"
fi
sizes[$service]=$size
total=$((total + size))
done
echo "Total size (all services, $PLATFORM only): $total bytes"
echo "total-size=$total" >> $GITHUB_OUTPUT
# Save to JSON
echo "{" > current-sizes.json
echo " \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"," >> current-sizes.json
echo " \"tag\": \"$TAG\"," >> current-sizes.json
echo " \"total\": $total," >> current-sizes.json
echo " \"services\": {" >> current-sizes.json
first=true
for service in "${services_list[@]}"; do
if [[ "$first" == "true" ]]; then
first=false
else
echo "," >> current-sizes.json
fi
echo " \"$service\": ${sizes[$service]}" >> current-sizes.json
done
echo " }" >> current-sizes.json
echo "}" >> current-sizes.json
echo "Current sizes saved:"
cat current-sizes.json
# Save services list for baseline measurement
printf '%s\n' "${services_list[@]}" > /tmp/services-list.txt
- name: Measure baseline
id: baseline
shell: bash
continue-on-error: true
env:
REGISTRY: ${{ inputs.registry }}
ORG: ${{ inputs.repository }}
TAG: ${{ inputs.baseline-tag }}
PLATFORM: ${{ inputs.platform }}
run: |
echo "Measuring baseline: $REGISTRY/$ORG/*:$TAG (platform: $PLATFORM)"
declare -A sizes
declare -a services_list
total=0
# Read services list from current measurement
while IFS= read -r service; do
services_list+=("$service")
# Map service name to image name (handle rocketchat -> rocket.chat)
if [[ "$service" == "rocketchat" ]] || [[ "$service" == "rocketchat-cov" ]]; then
image_name="rocket.chat"
[[ "$service" == "rocketchat-cov" ]] && image_name="rocket.chat-cov"
else
image_name="$service"
fi
image="$REGISTRY/$ORG/$image_name:$TAG"
echo " → Inspecting $image"
size=0
if manifest=$(docker manifest inspect "$image" 2>/dev/null); then
# Check if it's a manifest list (multi-arch)
if echo "$manifest" | jq -e '.manifests' > /dev/null 2>&1; then
# Manifest list - find the specified platform
echo " → Multi-arch manifest detected, filtering for $PLATFORM"
platform_digest=$(echo "$manifest" | jq -r --arg arch "$PLATFORM" '.manifests[] | select(.platform.architecture == $arch) | .digest' | head -1)
if [[ -n "$platform_digest" ]]; then
echo " → Inspecting $PLATFORM platform: $platform_digest"
if platform_manifest=$(docker manifest inspect "$REGISTRY/$ORG/$image_name@$platform_digest" 2>/dev/null); then
config_size=$(echo "$platform_manifest" | jq -r '.config.size // 0')
layers_size=$(echo "$platform_manifest" | jq '[.layers[]?.size // 0] | add // 0')
size=$((config_size + layers_size))
echo " → Size: $size bytes"
fi
else
echo " ⚠ Platform $PLATFORM not found in manifest"
fi
else
# Single arch manifest
config_size=$(echo "$manifest" | jq -r '.config.size // 0')
layers_size=$(echo "$manifest" | jq '[.layers[]?.size // 0] | add // 0')
size=$((config_size + layers_size))
fi
fi
sizes[$service]=$size
total=$((total + size))
done < /tmp/services-list.txt
echo "baseline-total=$total" >> $GITHUB_OUTPUT
echo "{" > baseline-sizes.json
echo " \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"," >> baseline-sizes.json
echo " \"tag\": \"$TAG\"," >> baseline-sizes.json
echo " \"total\": $total," >> baseline-sizes.json
echo " \"services\": {" >> baseline-sizes.json
first=true
for service in "${services_list[@]}"; do
if [[ "$first" == "true" ]]; then
first=false
else
echo "," >> baseline-sizes.json
fi
echo " \"$service\": ${sizes[$service]}" >> baseline-sizes.json
done
echo " }" >> baseline-sizes.json
echo "}" >> baseline-sizes.json
- name: Setup history storage
id: history
shell: bash
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
# Create a separate worktree for history branch
mkdir -p /tmp/history-worktree
# Try to fetch history branch
if git ls-remote --heads origin image-size-history | grep -q image-size-history; then
git fetch origin image-size-history
git worktree add /tmp/history-worktree image-size-history
else
# Create orphan branch for history in worktree
git worktree add --detach /tmp/history-worktree
cd /tmp/history-worktree
git checkout --orphan image-size-history
git rm -rf . 2>/dev/null || true
mkdir -p history
echo "# Image Size History" > README.md
echo "This branch stores historical image size data for tracking" >> README.md
git add README.md
git commit -m "Initialize image size history"
git push origin image-size-history
cd -
fi
mkdir -p /tmp/history-worktree/history
- name: Load historical data
shell: bash
run: |
# Load last 30 measurements and group by day (keep only last entry per day)
echo "[]" > history-data.json
if [[ -d /tmp/history-worktree/history ]]; then
jq -s '.' /tmp/history-worktree/history/*.json 2>/dev/null | jq '
sort_by(.timestamp) |
group_by(.timestamp[0:10]) |
map(.[-1]) |
.[-30:]
' > history-data.json || echo "[]" > history-data.json
fi
count=$(jq 'length' history-data.json)
echo "Loaded $count historical measurements (one per day)"
- name: Save current measurement to history
if: github.ref == 'refs/heads/develop'
shell: bash
env:
CI_PAT: ${{ inputs.ci-pat }}
run: |
timestamp=$(date -u +%Y%m%d-%H%M%S)
commit_sha="${{ github.sha }}"
# Add commit info to current measurement
jq --arg sha "$commit_sha" '. + {commit: $sha}' current-sizes.json > "/tmp/history-worktree/history/${timestamp}.json"
cd /tmp/history-worktree
git add "history/${timestamp}.json"
git commit -m "Add measurement for ${timestamp} (${commit_sha:0:7})"
git config --global user.email "ci@rocket.chat"
git config --global user.name "rocketchat-ci[bot]"
git config --global url.https://$CI_PAT@github.com/.insteadOf https://github.com/
git push origin image-size-history
cd -
echo "Saved measurement to history"
- name: Compare and generate report
id: compare
shell: bash
env:
SIZE_THRESHOLDS: ${{ inputs.size-thresholds }}
FAIL_THRESHOLDS: ${{ inputs.fail-thresholds }}
TAG: ${{ inputs.tag }}
BASELINE_TAG: ${{ inputs.baseline-tag }}
run: |
current_total=$(jq -r '.total' current-sizes.json)
if [[ ! -f baseline-sizes.json ]]; then
echo "No baseline available"
echo "size-diff=0" >> $GITHUB_OUTPUT
echo "size-diff-percent=0" >> $GITHUB_OUTPUT
echo "comment-triggered=false" >> $GITHUB_OUTPUT
cat > report.md << 'EOF'
# 📦 Docker Image Size Report
**Status:** First measurement - no baseline for comparison
**Total Size:** $(numfmt --to=iec-i --suffix=B $current_total)
EOF
exit 0
fi
baseline_total=$(jq -r '.total' baseline-sizes.json)
diff=$((current_total - baseline_total))
if [[ $baseline_total -gt 0 ]]; then
percent=$(awk "BEGIN {printf \"%.2f\", ($diff / $baseline_total) * 100}")
else
percent=0
fi
echo "size-diff=$diff" >> $GITHUB_OUTPUT
echo "size-diff-percent=$percent" >> $GITHUB_OUTPUT
# Only comment when size is bigger than baseline; optionally require per-image thresholds
THRESHOLDS="$SIZE_THRESHOLDS"
FAIL_THRESHOLDS="$FAIL_THRESHOLDS"
comment_triggered=false
fail_triggered=false
if [[ $diff -gt 0 ]]; then
if [[ -z "$THRESHOLDS" ]] || [[ "$THRESHOLDS" == "{}" ]]; then
comment_triggered=true
fi
fi
color="gray"
if (( $(awk "BEGIN {print ($percent > 0.01)}") )); then
color="red"
elif (( $(awk "BEGIN {print ($percent < -0.01)}") )); then
color="green"
fi
# Generate report
if [[ $diff -gt 0 ]]; then
emoji="📈"
badge="![](https://img.shields.io/badge/size-+${percent}%25-${color})"
sign="+"
elif [[ $diff -lt 0 ]]; then
emoji="📉"
badge="![](https://img.shields.io/badge/size--${percent}%25-${color})"
sign="-"
else
emoji="➡️"
badge="![](https://img.shields.io/badge/size-unchanged-${color})"
sign=""
fi
cat > report.md << EOF
# 📦 Docker Image Size Report
## $emoji Changes $badge
| Service | Current | Baseline | Change | Percent |
|---------|---------|----------|--------|---------|
| **sum of all images** | **$(numfmt --to=iec-i --suffix=B $current_total)** | **$(numfmt --to=iec-i --suffix=B $baseline_total)** | **${sign}$(numfmt --to=iec-i --suffix=B ${diff#-})** | $badge |
EOF
# Get services dynamically from current-sizes.json, sorted by size (largest first)
for service in $(jq -r '.services | to_entries | sort_by(-.value) | .[].key' current-sizes.json); do
current=$(jq -r ".services.\"$service\"" current-sizes.json)
baseline=$(jq -r ".services.\"$service\" // 0" baseline-sizes.json)
service_diff=$((current - baseline))
if [[ $baseline -gt 0 ]]; then
service_percent=$(awk "BEGIN {printf \"%.2f\", ($service_diff / $baseline) * 100}")
else
service_percent=0
fi
# Check per-image thresholds for comment trigger (only when size increased)
if [[ $diff -gt 0 ]] && [[ -n "$THRESHOLDS" ]] && [[ "$THRESHOLDS" != "{}" ]]; then
threshold_mb=$(echo "$THRESHOLDS" | jq -r ".\"$service\".mb // empty")
threshold_pct=$(echo "$THRESHOLDS" | jq -r ".\"$service\".percent // empty")
if [[ -n "$threshold_mb" ]] || [[ -n "$threshold_pct" ]]; then
exceeded=false
if [[ -n "$threshold_mb" ]] && [[ $service_diff -ge $(awk "BEGIN {printf \"%.0f\", $threshold_mb * 1048576}") ]]; then
exceeded=true
fi
if [[ -n "$threshold_pct" ]] && [[ $service_percent != "0.00" ]] && (( $(awk "BEGIN {print ($service_percent >= $threshold_pct)}") )); then
exceeded=true
fi
[[ "$exceeded" == "true" ]] && comment_triggered=true
fi
fi
# Check per-image fail thresholds (task fails when exceeded)
if [[ $diff -gt 0 ]] && [[ -n "$FAIL_THRESHOLDS" ]] && [[ "$FAIL_THRESHOLDS" != "{}" ]]; then
fail_mb=$(echo "$FAIL_THRESHOLDS" | jq -r ".\"$service\".mb // empty")
fail_pct=$(echo "$FAIL_THRESHOLDS" | jq -r ".\"$service\".percent // empty")
if [[ -n "$fail_mb" ]] || [[ -n "$fail_pct" ]]; then
exceeded=false
if [[ -n "$fail_mb" ]] && [[ $service_diff -ge $(awk "BEGIN {printf \"%.0f\", $fail_mb * 1048576}") ]]; then
exceeded=true
fi
if [[ -n "$fail_pct" ]] && [[ $service_percent != "0.00" ]] && (( $(awk "BEGIN {print ($service_percent >= $fail_pct)}") )); then
exceeded=true
fi
[[ "$exceeded" == "true" ]] && fail_triggered=true
fi
fi
color="gray"
if (( $(awk "BEGIN {print ($service_percent > 0.01)}") )); then
color="red"
elif (( $(awk "BEGIN {print ($service_percent < -0.01)}") )); then
color="green"
fi
if [[ $service_diff -gt 0 ]]; then
badge="![](https://img.shields.io/badge/size-+${service_percent}%25-${color})"
sign="+"
elif [[ $service_diff -lt 0 ]]; then
badge="![](https://img.shields.io/badge/size--${service_percent}%25-${color})"
sign="-"
else
badge="![](https://img.shields.io/badge/size-unchanged-${color})"
sign=""
fi
echo "| $service | $(numfmt --to=iec-i --suffix=B $current) | $(numfmt --to=iec-i --suffix=B $baseline) | ${sign}$(numfmt --to=iec-i --suffix=B ${service_diff#-}) | $badge |" >> report.md
done
# Generate historical trend chart
echo "" >> report.md
echo "## 📊 Historical Trend" >> report.md
echo "" >> report.md
# Load history and generate mermaid chart
history_count=$(jq 'length' history-data.json)
if [[ $history_count -gt 0 ]]; then
# Get all services from current build
all_services=$(jq -r '.services | keys | .[]' current-sizes.json | sort)
# Generate Mermaid chart data
x_labels=""
declare -A service_data
# Initialize service data arrays
for service in $all_services; do
service_data[$service]=""
done
# Process historical data
while IFS= read -r line; do
timestamp=$(echo "$line" | jq -r '.timestamp')
date_label=$(date -d "$timestamp" +"%m/%d %H:%M")
if [[ -z "$x_labels" ]]; then
x_labels="\"$date_label\""
else
x_labels="$x_labels, \"$date_label\""
fi
# Add data point for each service
for service in $all_services; do
size=$(echo "$line" | jq -r ".services.\"$service\" // 0")
size_gb=$(awk "BEGIN {printf \"%.2f\", $size / 1073741824}")
if [[ -z "${service_data[$service]}" ]]; then
service_data[$service]="$size_gb"
else
service_data[$service]="${service_data[$service]}, $size_gb"
fi
done
done < <(jq -c '.[]' history-data.json)
# Add current PR as last point
current_date=$(date -u +"%m/%d %H:%M")
x_labels="$x_labels, \"$current_date (PR)\""
for service in $all_services; do
size=$(jq -r ".services.\"$service\" // 0" current-sizes.json)
size_gb=$(awk "BEGIN {printf \"%.2f\", $size / 1073741824}")
service_data[$service]="${service_data[$service]}, $size_gb"
done
# Generate mermaid chart with multiple lines
cat >> report.md << EOF
\`\`\`mermaid
---
config:
theme: "dark"
xyChart:
width: 900
height: 400
---
xychart
title "Image Size Evolution by Service (Last 30 Days + This PR)"
x-axis [$x_labels]
y-axis "Size (GB)" 0 --> 0.5
EOF
# Add a line for each service
for service in $all_services; do
echo " line \"$service\" [${service_data[$service]}]" >> report.md
done
cat >> report.md << 'EOF'
```
EOF
# Add summary stats
min_size=$(jq '[.[].total] | min' history-data.json)
max_size=$(jq '[.[].total] | max' history-data.json)
avg_size=$(jq '[.[].total] | add / length' history-data.json)
cat >> report.md << EOF
**Statistics (last $history_count days):**
- 📊 Average: $(numfmt --to=iec-i --suffix=B ${avg_size%.*})
- ⬇️ Minimum: $(numfmt --to=iec-i --suffix=B $min_size)
- ⬆️ Maximum: $(numfmt --to=iec-i --suffix=B $max_size)
- 🎯 Current PR: $(numfmt --to=iec-i --suffix=B $current_total)
EOF
else
cat >> report.md << 'EOF'
*No historical data available yet. History tracking starts after merging to develop.*
EOF
fi
cat >> report.md << EOF
<details>
<summary>ℹ️ About this report</summary>
This report compares Docker image sizes from this build against the \`$BASELINE_TAG\` baseline.
- **Tag:** \`$TAG\`
- **Baseline:** \`$BASELINE_TAG\`
- **Timestamp:** $(date -u +"%Y-%m-%d %H:%M:%S UTC")
- **Historical data points:** $history_count
</details>
EOF
echo "comment-triggered=$comment_triggered" >> $GITHUB_OUTPUT
echo "failed=$fail_triggered" >> $GITHUB_OUTPUT
if [[ "$fail_triggered" == "true" ]]; then
echo "::error::Docker image size exceeded fail-thresholds (mb/percent). Check the report for details."
exit 1
fi
- name: Add report to Job Summary
if: always()
shell: bash
run: |
if [[ -f report.md ]]; then
cat report.md >> $GITHUB_STEP_SUMMARY
fi
- name: Cleanup worktree
if: always()
shell: bash
run: |
if [[ -d /tmp/history-worktree ]]; then
git worktree remove /tmp/history-worktree --force 2>/dev/null || true
fi
branding:
icon: 'package'
color: 'blue'

218
.github/actions/meteor-build/action.yml vendored Normal file
View File

@@ -0,0 +1,218 @@
name: 'Meteor Build'
description: 'Build Meteor bundle for production or coverage'
inputs:
type:
required: false
description: 'production or coverage'
default: 'production'
reset-meteor:
required: false
description: 'Reset Meteor'
node-version:
required: true
description: 'Node version'
NPM_TOKEN:
required: false
description: 'NPM token'
deno-version:
required: true
description: 'Deno version'
source-hash:
required: true
description: 'RC cache id (e.g. packages-build-cache-key + meteor apps/meteor archive hash from CI)'
runs:
using: composite
steps:
- name: Cache build
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
id: cache-build
with:
path: /tmp/Rocket.Chat.tar.gz
key: ${{ runner.arch }}-${{ runner.os }}-${{ inputs.type }}-rc-build-${{ inputs.source-hash }}
- name: Set Swap Space
uses: pierotofy/set-swap-space@49819abfb41bd9b44fb781159c033dba90353a7c # v1.0
if: steps.cache-build.outputs.cache-hit != 'true'
with:
swap-size-gb: 4
- name: Merge dependencies for build
shell: bash
if: steps.cache-build.outputs.cache-hit != 'true'
run: |
# Merge dependencies and devDependencies into a new 'dependencies' field
cd apps/meteor
cp package.json package.json.bak
jq '.dependencies = (.dependencies + .devDependencies) | del(.devDependencies)' package.json > package.json.tmp && mv package.json.tmp package.json
- name: Setup NodeJS
uses: ./.github/actions/setup-node
if: steps.cache-build.outputs.cache-hit != 'true'
with:
node-version: ${{ inputs.node-version }}
deno-version: ${{ inputs.deno-version }}
cache-modules: true
install: true
type: 'production'
NPM_TOKEN: ${{ inputs.NPM_TOKEN }}
# - name: Free disk space
# run: |
# sudo apt clean
# docker rmi $(docker image ls -aq)
# df -h
- name: Cache vite
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
if: steps.cache-build.outputs.cache-hit != 'true'
with:
path: ./node_modules/.vite
key: vite-local-cache-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('package.json') }}
restore-keys: |
vite-local-cache-${{ runner.arch }}-${{ runner.os }}-
- name: Cache meteor local
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
if: steps.cache-build.outputs.cache-hit != 'true'
with:
path: ./apps/meteor/.meteor/local
key: meteor-local-cache-${{ runner.arch }}-${{ runner.os }}-${{ inputs.type }}-${{ hashFiles('apps/meteor/.meteor/versions') }}
restore-keys: |
meteor-local-cache-${{ runner.arch }}-${{ runner.os }}-${{ inputs.type }}-
- name: Cache meteor
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
if: steps.cache-build.outputs.cache-hit != 'true'
with:
path: ~/.meteor
key: meteor-cache-${{ runner.arch }}-${{ runner.os }}-${{ inputs.type }}-${{ hashFiles('apps/meteor/.meteor/release') }}
restore-keys: |
meteor-cache-${{ runner.arch }}-${{ runner.os }}-${{ inputs.type }}-
- name: Install Meteor
shell: bash
if: steps.cache-build.outputs.cache-hit != 'true'
run: |
# Restore bin from cache
set +e
METEOR_SYMLINK_TARGET=$(readlink ~/.meteor/meteor)
METEOR_TOOL_DIRECTORY=$(dirname "$METEOR_SYMLINK_TARGET")
set -e
LAUNCHER=$HOME/.meteor/$METEOR_TOOL_DIRECTORY/scripts/admin/launch-meteor
if [ -e $LAUNCHER ]
then
echo "Cached Meteor bin found, restoring it"
sudo cp "$LAUNCHER" "/usr/local/bin/meteor"
else
echo "No cached Meteor bin found."
fi
# only install meteor if bin isn't found
command -v meteor >/dev/null 2>&1 || curl https://install.meteor.com | sed s/--progress-bar/-sL/g | /bin/sh
- name: Versions
shell: bash
if: steps.cache-build.outputs.cache-hit != 'true'
run: |
npm --versions
yarn -v
node -v
meteor --version
meteor npm --versions
meteor node -v
git version
- uses: rharkor/caching-for-turbo@00a0515f175df9fd2e15c4560144ad5fdbebb0c7 # v2.3.13
- name: Reset Meteor
shell: bash
if: ${{ steps.cache-build.outputs.cache-hit != 'true' && inputs.reset-meteor == 'true' }}
working-directory: ./apps/meteor
run: meteor reset
- name: Restore packages build
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: packages-build
path: /tmp
- name: Unpack packages build
shell: bash
run: |
tar -xzf /tmp/RocketChat-packages-build.tar.gz -C .
- name: Build Rocket.Chat
shell: bash
if: steps.cache-build.outputs.cache-hit != 'true'
env:
METEOR_PROFILE: 1000
BABEL_ENV: ${{ inputs.type }}
run: |
# check if BABEL_ENV is set to coverage
if [[ $BABEL_ENV == "coverage" ]]; then
echo -e "rocketchat:coverage\n" >> ./apps/meteor/.meteor/packages
# Inject swc-plugin-coverage-instrument into .swcrc for istanbul-compatible coverage
node -e "
const fs = require('fs');
const swcrc = JSON.parse(fs.readFileSync('./apps/meteor/.swcrc', 'utf8'));
swcrc.jsc.experimental = swcrc.jsc.experimental || {};
swcrc.jsc.experimental.plugins = swcrc.jsc.experimental.plugins || [];
swcrc.jsc.experimental.plugins.push(['swc-plugin-coverage-instrument', {}]);
fs.writeFileSync('./apps/meteor/.swcrc', JSON.stringify(swcrc, null, 2) + '\n');
"
echo "Coverage enabled (SWC istanbul plugin injected)"
fi
# Restore original package.json so meteor should not copy devDependencies
mv apps/meteor/package.json.bak apps/meteor/package.json
yarn build:ci
declare -a meter_modules_to_remove=(
"meteor/babel-compiler/node_modules/@meteorjs/swc-core/.swc/node_modules/@swc/core-darwin-arm64" # Removes 35M
"meteor/babel-compiler/node_modules/@meteorjs/swc-core/.swc/node_modules/@swc/core-linux-x64-musl" # Removes 58M
"meteor/babel-compiler/node_modules/@meteorjs/swc-core/.swc/node_modules/@swc/core-linux-arm64-musl" # Removes 44M
"meteor/babel-compiler/node_modules/typescript" # Removes 31M
# "meteor/babel-compiler/node_modules/@babel" # Removes 14M
"@rocket.chat/i18n/src" # Removes 16M
"typescript" # Removes 19M
# "@babel" # Removes 34M - Needed by Minimongo
)
du -s /tmp/dist/bundle
for dir_path in "${meter_modules_to_remove[@]}"; do
path=/tmp/dist/bundle/programs/server/npm/node_modules/${dir_path}
if [ -d "$path" ]; then
rm -rf "$path"
echo "Removed directory: $path"
else
echo "Path is not a directory or does not exist: $path"
fi
done
# Remove all .d.ts files from node_modules to reduce size
# Removes 184M
find /tmp/dist/bundle -type f -name "*.d.ts" -delete
du -s /tmp/dist/bundle
- name: Prepare build
shell: bash
if: steps.cache-build.outputs.cache-hit != 'true'
run: |
cd /tmp/dist
tar czf /tmp/Rocket.Chat.tar.gz bundle
- name: Store build
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: build-${{ inputs.type }}
path: /tmp/Rocket.Chat.tar.gz
overwrite: true
include-hidden-files: true

View File

@@ -0,0 +1,16 @@
name: 'Restore Packages Build'
description: 'Downloads and unpacks the packages build artifact'
runs:
using: 'composite'
steps:
- name: Restore packages build
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: packages-build
path: /tmp
- name: Unpack packages build
shell: bash
run: |
tar -xzf /tmp/RocketChat-packages-build.tar.gz -C .

120
.github/actions/setup-node/action.yml vendored Normal file
View File

@@ -0,0 +1,120 @@
name: 'Setup Node'
description: 'Setup NodeJS'
inputs:
node-version:
required: false
description: 'Node version. If not provided, read from package.json volta.node'
cache-modules:
required: false
description: 'Cache node_modules'
install:
required: false
description: 'Install dependencies'
type:
required: false
description: 'development or production'
default: 'development'
deno-version:
required: false
description: 'Deno version. If not provided, read from .tool-versions'
NPM_TOKEN:
required: false
description: 'NPM token'
HARDENED_MODE:
required: false
description: 'Hardened mode'
default: '0'
outputs:
node-version:
description: 'Node version'
value: ${{ steps.node-version.outputs.node-version }}
cache-deno-hit:
description: 'Exact key hit for Deno cache'
value: ${{ steps.cache-deno.outputs.cache-hit }}
runs:
using: composite
steps:
- name: Resolve tool versions
shell: bash
run: |
NODE_VERSION="${{ inputs.node-version }}"
if [ -z "$NODE_VERSION" ]; then
NODE_VERSION=$(node -p "require('./package.json').volta.node")
fi
echo "NODE_VERSION: ${NODE_VERSION}"
echo "NODE_VERSION=${NODE_VERSION}" >> $GITHUB_ENV
DENO_VERSION="${{ inputs.deno-version }}"
if [ -z "$DENO_VERSION" ]; then
DENO_VERSION=$(awk '$1=="deno"{ print $2 }' .tool-versions)
fi
echo "DENO_VERSION: ${DENO_VERSION}"
echo "DENO_VERSION=${DENO_VERSION}" >> $GITHUB_ENV
# Turbo local cache: use rharkor/caching-for-turbo in workflows — not stored here to avoid huge redundant keys.
- name: Cache Deno (apps)
if: inputs.cache-modules
id: cache-deno
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: packages/apps/.deno-cache
key: deno-${{ runner.os }}-${{ runner.arch }}-v${{ env.DENO_VERSION }}-${{ hashFiles('packages/apps/deno-runtime/deno.lock') }}
restore-keys: |
deno-${{ runner.os }}-${{ runner.arch }}-v${{ env.DENO_VERSION }}-
- name: Use Node.js ${{ env.NODE_VERSION }}
id: node-version
uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0
with:
node-version: ${{ env.NODE_VERSION }}
cache: ${{ inputs.cache-modules && 'yarn' || '' }}
- name: Use Deno ${{ env.DENO_VERSION }}
uses: denoland/setup-deno@667a34cdef165d8d2b2e98dde39547c9daac7282 # v2.0.4
with:
deno-version: ${{ env.DENO_VERSION }}
- name: Cache mongodb-memory-server binary
if: inputs.cache-modules
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
with:
path: ${{ runner.temp }}/mongodb-memory-server
key: mongoms-${{ runner.arch }}-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Configure mongodb-memory-server cache
shell: bash
run: |
CACHE_DIR="${{ runner.temp }}/mongodb-memory-server"
echo "MONGOMS_DOWNLOAD_DIR=$CACHE_DIR" >> $GITHUB_ENV
echo "MONGOMS_PREFER_GLOBAL_PATH=false" >> $GITHUB_ENV
- name: yarn login
shell: bash
if: inputs.NPM_TOKEN
run: |
echo "//registry.npmjs.org/:_authToken=${{ inputs.NPM_TOKEN }}" > ~/.npmrc
- name: yarn config
if: inputs.install
shell: bash
run: |
yarn config set supportedArchitectures --json '{"os": ["linux"], "cpu": ["arm64", "x64"], "libc": ["glibc", "musl"]}'
- name: yarn install
if: inputs.install && inputs.type == 'development'
shell: bash
run: YARN_ENABLE_HARDENED_MODE=${{ inputs.HARDENED_MODE }} yarn
- name: yarn install production
if: inputs.install && inputs.type == 'production'
shell: bash
run: YARN_ENABLE_HARDENED_MODE=${{ inputs.HARDENED_MODE }} yarn workspaces focus --all --production
- name: restore yarn config file
if: inputs.install
shell: bash
run: git checkout -- .yarnrc.yml

View File

@@ -0,0 +1,21 @@
name: Setup Playwright
description: 'Setup Playwright binaries and dependencies'
runs:
using: 'composite'
steps:
- name: Cache Playwright binaries
uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5
id: cache-playwright
with:
path: |
~/.cache/ms-playwright
# This is the version of Playwright that we are using, if you are willing to upgrade, you should update this.
key: playwright-${{ runner.arch }}-${{ runner.os }}-1.52.0
- name: Install Playwright
shell: bash
if: steps.cache-playwright.outputs.cache-hit != 'true'
working-directory: .
run: npx playwright install --with-deps

View File

@@ -0,0 +1,26 @@
name: Update Version Durability
description: Update Version Durability page on Document360
inputs:
LTS_VERSIONS:
required: true
description: Comma separated list of LTS versions
GH_TOKEN:
required: true
description: GitHub API Token
D360_TOKEN:
required: true
description: Document360 API Token
D360_ARTICLE_ID:
required: true
description: Document360 Article ID
D360_USER_ID:
required: true
description: Document360 User ID used to fork and publish the article
PUBLISH:
required: true
description: Publish Draft
runs:
using: node20
main: index.js

View File

@@ -0,0 +1,228 @@
import 'colors';
import axios from 'axios';
import * as Diff from 'diff';
import semver from 'semver';
import crypto from 'crypto';
import fs from 'fs/promises';
import BeautyHtml from 'beauty-html';
import { DOMParser } from '@xmldom/xmldom';
import core from '@actions/core';
import { Octokit } from '@octokit/rest';
const D360_TOKEN = core.getInput('D360_TOKEN');
const D360_ARTICLE_ID = core.getInput('D360_ARTICLE_ID');
const D360_USER_ID = core.getInput('D360_USER_ID');
const PUBLISH = core.getInput('PUBLISH') === 'true';
const LTS_VERSIONS = (core.getInput('LTS_VERSIONS') || '7.10').split(',').map((v) => v.trim());
const octokit = new Octokit({
auth: core.getInput('GH_TOKEN'),
});
async function requestDocument360(method = 'get', api, data = {}) {
return axios.request({
method,
maxBodyLength: Infinity,
url: `https://apihub.us.document360.io/v1/${api}`,
headers: {
'accept': 'application/json',
'api_token': D360_TOKEN,
},
data,
});
}
function md5(text) {
return crypto.createHash('md5').update(text).digest("hex");
}
async function generateTable({ owner, repo } = {}) {
const response = await requestDocument360('get', `Articles/${D360_ARTICLE_ID}/en`);
// console.log(response.data.data);
// const releasesResult = JSON.parse(await fs.readFile('/tmp/releasesResult'));
const releasesResult = await octokit.paginate(octokit.repos.listReleases.endpoint.merge({ owner, repo, per_page: 100 }));
// await fs.writeFile('/tmp/releasesResult', JSON.stringify(releasesResult));
const releases = releasesResult
.filter((release) => !release.tag_name.includes('-rc') && semver.gte(release.tag_name, '1.0.0'))
.sort((a, b) => semver.compare(b.tag_name, a.tag_name));
const releasesMap = {};
for (const release of releases) {
release.releaseDate = new Date(release.published_at);
releasesMap[release.tag_name] = release;
}
let index = 0;
// eslint-disable-next-line no-constant-condition
while (true) {
const release = releases[index];
release.minor_tag = release.tag_name.replace(/\.\d+$/, '');
release.minorRelease = releasesMap[`${release.minor_tag}.0`];
if (!releases[index + 1]) {
break;
}
const currentVersion = semver.parse(release.tag_name);
const previousVersion = semver.parse(releases[index + 1].tag_name);
releases[index + 1].nextRelease = release;
// Remove duplicated due to patches
if (currentVersion.major === previousVersion.major && currentVersion.minor === previousVersion.minor) {
releases.splice(index + 1, 1);
continue;
}
// Mark LTS
if (LTS_VERSIONS.includes(`${currentVersion.major}.${currentVersion.minor}`)) {
release.lts = true;
}
index++;
}
releases[0].last = true;
const releaseData = [];
for (const { tag_name, html_url, lts, last, nextRelease, minorRelease, minor_tag} of releases) {
let supportDate;
let supportDateStart;
let releasedAt = new Date(minorRelease.releaseDate);
releasedAt.setDate(1);
let minorDate = new Date(minorRelease.releaseDate);
minorDate.setDate(1);
supportDateStart = minorDate;
supportDate = new Date(minorDate);
supportDate.setMonth(supportDate.getMonth() + (lts ? 12 : 6));
releaseData.push({
release: {
version: minor_tag,
releasedAt,
extendedSupport: {
start: supportDateStart,
end: supportDate,
},
lts: lts === true,
},
latestPatch: {
version: tag_name,
url: html_url,
}
})
}
function header({data, salt = ''}) {
return [
'<th colspan="1" data-vertical-align="middle" data-horizontal-align="left" rowspan="1" style="vertical-align:middle;text-align:left;">',
`<p data-block-id="${md5(salt+data)}">${data}</p>`,
'</th>',
].join('');
}
function line({data, salt = ''}) {
return [
'<td colspan="1" rowspan="1" data-vertical-align="middle" data-horizontal-align="left" style="vertical-align:middle;text-align:left;">',
`<p data-block-id="${md5(salt+data)}">${data}</p>`,
'</td>',
].join('');
}
const text = [
'<tr>',
header({data: 'Rocket.Chat Release'}),
header({data: 'Released At'}),
header({data: 'End of Life'}),
'</tr>',
];
releaseData.forEach(({release, latestPatch}) => {
const releasedAt = release.releasedAt.toLocaleString('en', { month: 'short', year: "numeric" });
const endOfLife = !release.extendedSupport
? 'TBD'
: release.extendedSupport.end.toLocaleString('en', { month: 'short', year: "numeric" });
const link = `${release.version}${release.lts ? " LTS" : ""} (<a href="${latestPatch.url}" target="_blank" translate="no">${latestPatch.version}</a>)`;
text.push(
'<tr>',
line({data: link}),
line({data: releasedAt, salt: release.version}),
line({data: endOfLife, salt: release.version}),
'</tr>',
);
});
const content = response.data.data.html_content.replace(/<tbody>.+(\n.+)*<\/tbody>/m, `<tbody>${text.join('').replace(/\t|\n/g, '')}</tbody>`)
// console.log(content);
const parser = new BeautyHtml({ parser: DOMParser });
const diff = Diff.diffLines(parser.beautify(response.data.data.html_content), parser.beautify(content), { ignoreWhitespace: true, newlineIsToken: false });
diff.forEach((item) => {
let color = 'green';
if (item.removed) {
color = 'red';
}
if (item.removed || item.added) {
item.value.split('\n').forEach((line) => {
if (line === '') { return };
console.log(`${item.removed ? '-' : '+'} ${line}`[color]);
})
}
});
if (diff.length === 1) {
console.log('No changes found');
return;
}
if (response.data.data.status === 3) {
console.log('forking article', response.data.data.version_number);
const forkResponse = await requestDocument360('put', `Articles/${D360_ARTICLE_ID}/fork`, {
lang_code: "en",
user_id: D360_USER_ID,
version_number: response.data.data.version_number,
});
console.log(forkResponse.data);
if (!forkResponse.data.success) {
throw new Error(`Failed to fork article: ${JSON.stringify(forkResponse.data.errors)}`);
}
}
console.log('Updating article');
const updateResponse = await requestDocument360('put', `Articles/${D360_ARTICLE_ID}/en`, {
content,
});
console.log(updateResponse.data);
if (PUBLISH) {
console.log('publishing article', updateResponse.data.data.version_number);
const forkResponse = await requestDocument360('post', `Articles/${D360_ARTICLE_ID}/en/publish`, {
user_id: D360_USER_ID,
version_number: updateResponse.data.data.version_number,
publish_message: 'Update support versions table via GitHub Action',
});
console.log(forkResponse.data);
}
}
generateTable({ owner: 'RocketChat', repo: 'Rocket.Chat' });

View File

@@ -0,0 +1,717 @@
{
"name": "scripts",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "scripts",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@actions/core": "^1.10.1",
"@octokit/rest": "^21.0.2",
"@xmldom/xmldom": "^0.8.15",
"axios": "^1.18.1",
"beauty-html": "^1.3.1",
"colors": "^1.4.0",
"diff": "^5.1.0",
"semver": "^7.5.4"
}
},
"node_modules/@actions/core": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz",
"integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==",
"license": "MIT",
"dependencies": {
"@actions/exec": "^1.1.1",
"@actions/http-client": "^2.0.1"
}
},
"node_modules/@actions/exec": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
"license": "MIT",
"dependencies": {
"@actions/io": "^1.0.1"
}
},
"node_modules/@actions/http-client": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.1.tgz",
"integrity": "sha512-KhC/cZsq7f8I4LfZSJKgCvEwfkE8o1538VoBeoGzokVLLnbFDEAdFD3UhoMklxo2un9NJVBdANOresx7vTHlHw==",
"dependencies": {
"tunnel": "^0.0.6",
"undici": "^5.25.4"
}
},
"node_modules/@actions/io": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==",
"license": "MIT"
},
"node_modules/@octokit/auth-token": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-5.1.1.tgz",
"integrity": "sha512-rh3G3wDO8J9wSjfI436JUKzHIxq8NaiL0tVeB2aXmG6p/9859aUOAjA9pmSPNGGZxfwmaJ9ozOJImuNVJdpvbA==",
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/core": {
"version": "6.1.6",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-6.1.6.tgz",
"integrity": "sha512-kIU8SLQkYWGp3pVKiYzA5OSaNF5EE03P/R8zEmmrG6XwOg5oBjXyQVVIauQ0dgau4zYhpZEhJrvIYt6oM+zZZA==",
"license": "MIT",
"dependencies": {
"@octokit/auth-token": "^5.0.0",
"@octokit/graphql": "^8.2.2",
"@octokit/request": "^9.2.3",
"@octokit/request-error": "^6.1.8",
"@octokit/types": "^14.0.0",
"before-after-hook": "^3.0.2",
"universal-user-agent": "^7.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/core/node_modules/@octokit/openapi-types": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz",
"integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
"license": "MIT"
},
"node_modules/@octokit/core/node_modules/@octokit/types": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz",
"integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^25.1.0"
}
},
"node_modules/@octokit/endpoint": {
"version": "10.1.4",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-10.1.4.tgz",
"integrity": "sha512-OlYOlZIsfEVZm5HCSR8aSg02T2lbUWOsCQoPKfTXJwDzcHQBrVBGdGXb89dv2Kw2ToZaRtudp8O3ZIYoaOjKlA==",
"license": "MIT",
"dependencies": {
"@octokit/types": "^14.0.0",
"universal-user-agent": "^7.0.2"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz",
"integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
"license": "MIT"
},
"node_modules/@octokit/endpoint/node_modules/@octokit/types": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz",
"integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^25.1.0"
}
},
"node_modules/@octokit/graphql": {
"version": "8.2.2",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-8.2.2.tgz",
"integrity": "sha512-Yi8hcoqsrXGdt0yObxbebHXFOiUA+2v3n53epuOg1QUgOB6c4XzvisBNVXJSl8RYA5KrDuSL2yq9Qmqe5N0ryA==",
"license": "MIT",
"dependencies": {
"@octokit/request": "^9.2.3",
"@octokit/types": "^14.0.0",
"universal-user-agent": "^7.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz",
"integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
"license": "MIT"
},
"node_modules/@octokit/graphql/node_modules/@octokit/types": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz",
"integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^25.1.0"
}
},
"node_modules/@octokit/openapi-types": {
"version": "23.0.1",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-23.0.1.tgz",
"integrity": "sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==",
"license": "MIT"
},
"node_modules/@octokit/plugin-paginate-rest": {
"version": "11.4.2",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-11.4.2.tgz",
"integrity": "sha512-BXJ7XPCTDXFF+wxcg/zscfgw2O/iDPtNSkwwR1W1W5c4Mb3zav/M2XvxQ23nVmKj7jpweB4g8viMeCQdm7LMVA==",
"license": "MIT",
"dependencies": {
"@octokit/types": "^13.7.0"
},
"engines": {
"node": ">= 18"
},
"peerDependencies": {
"@octokit/core": ">=6"
}
},
"node_modules/@octokit/plugin-request-log": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-5.3.1.tgz",
"integrity": "sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==",
"license": "MIT",
"engines": {
"node": ">= 18"
},
"peerDependencies": {
"@octokit/core": ">=6"
}
},
"node_modules/@octokit/plugin-rest-endpoint-methods": {
"version": "13.5.0",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-13.5.0.tgz",
"integrity": "sha512-9Pas60Iv9ejO3WlAX3maE1+38c5nqbJXV5GrncEfkndIpZrJ/WPMRd2xYDcPPEt5yzpxcjw9fWNoPhsSGzqKqw==",
"license": "MIT",
"dependencies": {
"@octokit/types": "^13.10.0"
},
"engines": {
"node": ">= 18"
},
"peerDependencies": {
"@octokit/core": ">=6"
}
},
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": {
"version": "24.2.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
"license": "MIT"
},
"node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
"version": "13.10.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^24.2.0"
}
},
"node_modules/@octokit/request": {
"version": "9.2.4",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-9.2.4.tgz",
"integrity": "sha512-q8ybdytBmxa6KogWlNa818r0k1wlqzNC+yNkcQDECHvQo8Vmstrg18JwqJHdJdUiHD2sjlwBgSm9kHkOKe2iyA==",
"license": "MIT",
"dependencies": {
"@octokit/endpoint": "^10.1.4",
"@octokit/request-error": "^6.1.8",
"@octokit/types": "^14.0.0",
"fast-content-type-parse": "^2.0.0",
"universal-user-agent": "^7.0.2"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/request-error": {
"version": "6.1.8",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-6.1.8.tgz",
"integrity": "sha512-WEi/R0Jmq+IJKydWlKDmryPcmdYSVjL3ekaiEL1L9eo1sUnqMJ+grqmC9cjk7CA7+b2/T397tO5d8YLOH3qYpQ==",
"license": "MIT",
"dependencies": {
"@octokit/types": "^14.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz",
"integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
"license": "MIT"
},
"node_modules/@octokit/request-error/node_modules/@octokit/types": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz",
"integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^25.1.0"
}
},
"node_modules/@octokit/request/node_modules/@octokit/openapi-types": {
"version": "25.1.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-25.1.0.tgz",
"integrity": "sha512-idsIggNXUKkk0+BExUn1dQ92sfysJrje03Q0bv0e+KPLrvyqZF8MnBpFz8UNfYDwB3Ie7Z0TByjWfzxt7vseaA==",
"license": "MIT"
},
"node_modules/@octokit/request/node_modules/@octokit/types": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-14.1.0.tgz",
"integrity": "sha512-1y6DgTy8Jomcpu33N+p5w58l6xyt55Ar2I91RPiIA0xCJBXyUAhXCcmZaDWSANiha7R9a6qJJ2CRomGPZ6f46g==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^25.1.0"
}
},
"node_modules/@octokit/rest": {
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-21.1.1.tgz",
"integrity": "sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==",
"license": "MIT",
"dependencies": {
"@octokit/core": "^6.1.4",
"@octokit/plugin-paginate-rest": "^11.4.2",
"@octokit/plugin-request-log": "^5.3.1",
"@octokit/plugin-rest-endpoint-methods": "^13.3.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/@octokit/types": {
"version": "13.8.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.8.0.tgz",
"integrity": "sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^23.0.1"
}
},
"node_modules/@xmldom/xmldom": {
"version": "0.8.15",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.15.tgz",
"integrity": "sha512-/5NV/vDALVFDXgLmfsy9TRCBlKwO2LNBFzpzvb9iIj+jR+eSc6DLYYvVOdivT/jm7MtU6TebYuRmzEOI7w40UA==",
"license": "MIT",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/agent-base": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
"integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
"license": "MIT",
"dependencies": {
"debug": "4"
},
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"license": "MIT"
},
"node_modules/axios": {
"version": "1.18.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.18.1.tgz",
"integrity": "sha512-3nTvFlvpn9Zu/RkHUqtc7/+al4UpRW5az71ap5zccp6e8RAYEzhMTecX8Dz1wWDYrPpUoB1HAQEGEAEvUr7S9g==",
"license": "MIT",
"dependencies": {
"follow-redirects": "^1.16.0",
"form-data": "^4.0.5",
"https-proxy-agent": "^5.0.1",
"proxy-from-env": "^2.1.0"
}
},
"node_modules/beauty-html": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/beauty-html/-/beauty-html-1.3.1.tgz",
"integrity": "sha512-c0iKWc527T2MQcYhIMMw9OHN8kcXSf/ijadWzURhZWi6e6cnBXxAQ5IlXbYd0YZJE9lFtXRB1fJVQrvJf5DmPQ=="
},
"node_modules/before-after-hook": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-3.0.2.tgz",
"integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A=="
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
"engines": {
"node": ">=0.1.90"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/diff": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-5.2.2.tgz",
"integrity": "sha512-vtcDfH3TOjP8UekytvnHH1o1P4FcUdt4eQ1Y+Abap1tk/OB2MWQvcwS2ClCd1zuIhc3JKOx6p3kod8Vfys3E+A==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-set-tostringtag": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.6",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/fast-content-type-parse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-2.0.1.tgz",
"integrity": "sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "MIT"
},
"node_modules/follow-redirects": {
"version": "1.16.0",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
"integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"license": "MIT",
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/form-data": {
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz",
"integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==",
"license": "MIT",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.4",
"mime-types": "^2.1.35"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-tostringtag": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"license": "MIT",
"dependencies": {
"has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz",
"integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/https-proxy-agent": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
"integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
"license": "MIT",
"dependencies": {
"agent-base": "6",
"debug": "4"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"license": "MIT",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/proxy-from-env": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
"integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
"license": "MIT",
"engines": {
"node": ">=10"
}
},
"node_modules/semver": {
"version": "7.6.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
"integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/tunnel": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/tunnel/-/tunnel-0.0.6.tgz",
"integrity": "sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==",
"engines": {
"node": ">=0.6.11 <=0.7.0 || >=0.7.3"
}
},
"node_modules/undici": {
"version": "6.28.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.28.0.tgz",
"integrity": "sha512-LIY910g9TI13YS95lrMFrs8Rm/u/irgHeTWoKCoteeJ04CUJ92eEfj0rVn+7VKMPBpUPiUoBKfhNyLI23EE/KA==",
"license": "MIT",
"engines": {
"node": ">=18.17"
}
},
"node_modules/universal-user-agent": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz",
"integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==",
"license": "ISC"
}
}
}

View File

@@ -0,0 +1,24 @@
{
"name": "scripts",
"version": "1.0.0",
"type": "module",
"description": "",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"@actions/core": "^1.10.1",
"@octokit/rest": "^21.0.2",
"axios": "^1.18.1",
"beauty-html": "^1.3.1",
"colors": "^1.4.0",
"diff": "^5.1.0",
"semver": "^7.5.4",
"@xmldom/xmldom": "^0.8.15"
},
"overrides": {
"undici": "6.28.0"
}
}

212
.github/agents/bug-resolution-agent.md vendored Normal file
View File

@@ -0,0 +1,212 @@
---
name: Bug Resolution Agent
description: |
A focused agent that resolves GitHub issues by applying minimal, test-driven fixes.
It prioritizes reproducible tests (when feasible), enforces lint and TypeScript compliance,
and avoids refactoring or unrelated changes.
---
# Bug Resolution Agent
## Purpose
This agent resolves bugs in a precise and minimal manner.
Its goal is to:
- Reproduce the issue (preferably with an automated test)
- Apply the smallest possible fix
- Ensure quality gates (tests, lint, TypeScript) pass
- Create a clear changeset
- Keep the PR easy to review
The agent must **not introduce refactors, performance optimizations, or scope expansion**.
---
## Operating Principles
1. **Minimal Surface Area**
- Only modify what is strictly necessary to resolve the issue.
- Do not refactor unrelated code.
- Do not introduce structural improvements unless required to fix the bug.
2. **Test-First When Feasible**
- If the issue can be reproduced via automated test (especially API or black-box behavior), write a failing test first.
- The test must fail before the fix and pass after the fix.
3. **Quality Gates Are Mandatory**
- All existing tests must pass.
- Lint must pass with no new warnings or errors.
- TypeScript type checking must pass without errors.
- Build must succeed.
4. **Scope Discipline**
- If additional problems are discovered, do not fix them in the same PR.
- Document them as TODOs for future issues (see Section: Documenting Out-of-Scope Findings).
---
## Documenting Out-of-Scope Findings
When you discover problems outside the current scope during your work, **do not fix them**. Instead, create a detailed TODO comment or document them in the PR description so they can become separate issues.
### TODO Format
Add a TODO comment in the code near where the problem was found.
**Type prefixes** (same as PR conventions):
- `bug` - A bug that needs to be fixed
- `feat` - A new feature opportunity
- `refactor` - Code that needs refactoring
- `chore` - Maintenance tasks (dependencies, configs, etc.)
- `test` - Missing or incomplete tests
**Optional labels** (GitHub labels in brackets):
- `[security]` - Security-related issues
- `[performance]` - Performance improvements
- `[a11y]` - Accessibility issues
- `[i18n]` - Internationalization issues
- `[breaking]` - Breaking changes
- Any other GitHub label relevant to the issue
```typescript
// TODO: type [optional-label] <Brief title>
// Problem: <Detailed description of what is wrong>
// Location: <File path and function/component name>
// Impact: <How this affects the system - severity, affected features>
// Suggested fix: <High-level approach to resolve>
// Discovered while: <Reference to current PR/issue>
```
### Example
```typescript
// TODO: bug [high-priority] Race condition in message delivery
// Problem: When multiple messages are sent rapidly, the order is not guaranteed
// due to async handling without proper sequencing.
// Location: apps/meteor/server/services/messages/sendMessage.ts - sendToChannel()
// Impact: Medium - Users may see messages out of order in high-traffic channels
// Suggested fix: Implement a message queue with sequence numbers or use
// optimistic locking on the channel's lastMessageAt timestamp.
// Discovered while: Fixing #12345 - Message duplication bug
```
### In PR Description
Also list discovered issues in the PR description under a "Discovered Issues" section:
```markdown
## Discovered Issues (Out of Scope)
The following issues were discovered during this work and should be addressed in separate PRs:
- `bug` [high-priority]: **Race condition in message delivery** - See TODO in `sendMessage.ts:142`
- `test`: **Missing input validation tests** - See TODO in `userController.ts:87`
```
---
## Step-by-Step Execution Flow
### 1. Analyze the Issue
- Carefully read the issue description.
- Identify:
- Expected behavior
- Actual behavior
- Reproduction steps
- Do not assume undocumented requirements.
---
### 2. Determine Test Feasibility
- Can the bug be reproduced through:
- Unit tests?
- Integration tests?
- API black-box tests?
If **yes** → proceed to Step 3.
If **no** → proceed directly to Step 4.
---
### 3. Write a Failing Test (Preferred Path)
- Implement a test that reproduces the bug.
- The test must:
- Reflect the reported behavior
- Fail under the current implementation
- Use the project's existing test framework and conventions.
- Avoid introducing new testing patterns unless strictly required.
---
### 4. Apply the Minimal Fix
- Implement the smallest change that resolves the failing behavior.
- Do not:
- Refactor unrelated modules
- Rename symbols without necessity
- Change formatting beyond what lint enforces
- Improve performance unless directly tied to the bug
---
### 5. Validate the Fix
Ensure:
- The newly created test passes.
- All existing tests pass.
- Lint passes.
- TypeScript compilation passes.
- Build succeeds.
If any of these fail, adjust only what is required to restore compliance.
---
### 6. Create a Changeset
Create a concise changeset entry including:
- What was broken
- What was changed
- How it was validated (test reference)
Keep it factual and objective.
---
### 7. Open the Pull Request
The PR must:
- Clearly reference the original issue.
- Highlight the test added (if applicable).
- Describe the minimal fix applied.
- Avoid mentioning improvements outside the issue scope.
---
## Non-Goals
This agent must NOT:
- Perform refactoring
- Improve unrelated code quality
- Introduce stylistic changes
- Expand scope beyond the issue
- Combine multiple bug fixes in one PR
---
## Success Criteria
A successful run results in:
- A minimal diff
- A reproducible test (when feasible)
- Passing CI (tests, lint, TypeScript)
- A clear and review-friendly Pull Request

View File

@@ -0,0 +1,335 @@
---
name: Feature Development Agent
description: |
A comprehensive agent that implements new features following best practices,
with proper planning, testing, documentation, and incremental delivery.
It ensures features are well-designed, tested, and maintainable.
---
# Feature Development Agent
## Purpose
This agent implements new features in a structured and maintainable way.
Its goal is to:
- Understand and clarify feature requirements
- Design a clean, extensible implementation
- Write comprehensive tests for new functionality
- Ensure quality gates pass
- Create well-documented, reviewable PRs
- Follow existing patterns and conventions
The agent must **focus only on the specified feature scope** and avoid scope creep.
---
## Operating Principles
1. **Requirements First**
- Fully understand the feature before writing code.
- Clarify ambiguities before implementation.
- Define acceptance criteria upfront.
2. **Design Before Code**
- Plan the architecture and approach.
- Consider edge cases and error handling.
- Identify integration points with existing code.
3. **Test-Driven Development**
- Write tests that define expected behavior.
- Tests should cover happy paths and edge cases.
- Tests serve as living documentation.
4. **Quality Gates Are Mandatory**
- All tests (new and existing) must pass.
- Lint must pass with no new warnings or errors.
- TypeScript type checking must pass without errors.
- Build must succeed.
5. **Incremental Delivery**
- Break features into deliverable increments.
- Each increment should be functional and valuable.
- Prefer feature flags for large features.
6. **Consistency**
- Follow existing code patterns and conventions.
- Maintain consistency with the codebase style.
- Reuse existing utilities and components.
7. **Scope Discipline**
- Focus only on the specified feature requirements.
- Do not fix unrelated bugs discovered during implementation.
- Do not refactor existing code beyond what's needed for the feature.
- Document discovered problems as TODOs for future issues (see Section: Documenting Out-of-Scope Findings).
---
## Documenting Out-of-Scope Findings
When you discover bugs, technical debt, or improvement opportunities outside the current feature scope, **do not fix them**. Instead, create a detailed TODO comment or document them in the PR description so they can become separate issues.
### TODO Format
Add a TODO comment in the code near where the problem was found.
**Type prefixes** (same as PR conventions):
- `bug` - A bug that needs to be fixed
- `feat` - A new feature opportunity
- `refactor` - Code that needs refactoring
- `chore` - Maintenance tasks (dependencies, configs, etc.)
- `test` - Missing or incomplete tests
**Optional labels** (GitHub labels in brackets):
- `[security]` - Security-related issues
- `[performance]` - Performance improvements
- `[a11y]` - Accessibility issues
- `[i18n]` - Internationalization issues
- `[breaking]` - Breaking changes
- Any other GitHub label relevant to the issue
```typescript
// TODO: type [optional-label] <Brief title>
// Problem: <Detailed description of what is wrong>
// Location: <File path and function/component name>
// Impact: <How this affects the system - severity, affected features>
// Suggested fix: <High-level approach to resolve>
// Discovered while: <Reference to current PR/issue>
```
### Example
```typescript
// TODO: bug [security] Missing rate limiting on user search endpoint
// Problem: The /api/v1/users.search endpoint has no rate limiting,
// allowing potential abuse through rapid sequential requests.
// Location: apps/meteor/app/api/server/v1/users.ts - searchUsers()
// Impact: High - Security vulnerability, potential DoS vector
// Suggested fix: Add rate limiting middleware similar to login endpoints,
// suggest 10 requests per minute per user.
// Discovered while: Implementing user mention autocomplete feature #54321
```
### In PR Description
Also list discovered issues in the PR description under a "Discovered Issues" section:
```markdown
## Discovered Issues (Out of Scope)
The following issues were discovered during this feature implementation and should be addressed in separate PRs:
- `bug` [security]: **Missing rate limiting on user search** - See TODO in `users.ts:234`
- `refactor`: **Inconsistent error handling in API** - See TODO in `channels.ts:156`
- `chore`: **Outdated TypeScript types** - See TODO in `types/user.d.ts:12`
```
---
## Step-by-Step Execution Flow
### 1. Analyze Feature Requirements
- Carefully read the feature request/specification.
- Identify:
- Core functionality
- User stories/use cases
- Acceptance criteria
- Non-functional requirements (performance, security)
- List any unclear or ambiguous requirements.
- Do not assume undocumented behavior.
---
### 2. Research Existing Codebase
- Identify related existing functionality.
- Find:
- Similar features to reference
- Existing patterns to follow
- Utilities and helpers to reuse
- Integration points
- Understand the architectural context.
---
### 3. Design the Implementation
Create a technical design covering:
- **Data Model**: New types, interfaces, schemas
- **API Design**: Endpoints, methods, signatures
- **Component Structure**: Files, modules, classes
- **State Management**: How data flows
- **Error Handling**: Expected failures and responses
- **Security**: Authentication, authorization, validation
- **Performance**: Considerations for scale
---
### 4. Define Test Strategy
Plan tests at multiple levels:
- **Unit Tests**: Individual functions and components
- **Integration Tests**: Component interactions
- **API Tests**: Endpoint behavior (if applicable)
- **E2E Tests**: User workflows (if applicable)
Define:
- Happy path scenarios
- Edge cases
- Error scenarios
- Boundary conditions
---
### 5. Implement Incrementally
For each implementation increment:
#### 5.1 Write Tests First
- Define expected behavior through tests.
- Tests should initially fail (TDD red phase).
#### 5.2 Implement the Code
- Write the minimum code to pass tests.
- Follow existing patterns and conventions.
- Add proper TypeScript types.
- Include error handling.
#### 5.3 Refactor if Needed
- Clean up the implementation.
- Ensure code quality standards are met.
- Keep tests passing.
#### 5.4 Verify Quality Gates
- Run all tests.
- Run lint.
- Run TypeScript compilation.
- Build the project.
---
### 6. Add Documentation
Document the new feature:
- **Code Comments**: Complex logic explanation
- **JSDoc/TSDoc**: Public APIs and functions
- **README Updates**: If feature affects setup/usage
- **API Documentation**: New endpoints (if applicable)
- **Inline Documentation**: Configuration options
---
### 7. Create a Changeset
Create a changeset entry including:
- Feature name and description
- Key functionality added
- Any breaking changes
- Migration notes (if applicable)
---
### 8. Open the Pull Request
The PR must include:
- Clear description of the feature
- Link to the original issue/specification
- Summary of implementation approach
- List of new tests added
- Screenshots/recordings (if UI changes)
- Testing instructions for reviewers
- Any deployment considerations
---
## Implementation Guidelines
### Code Structure
- Place code in appropriate directories following project conventions.
- Create new files for distinct functionality.
- Keep files focused and reasonably sized.
### Type Safety
- Define explicit types for all new code.
- Avoid `any` types.
- Use generics where appropriate.
- Export types that consumers need.
### Error Handling
- Handle all expected error cases.
- Provide meaningful error messages.
- Use appropriate error types/codes.
- Log errors appropriately.
### Security
- Validate all inputs.
- Sanitize outputs where needed.
- Follow authentication/authorization patterns.
- Never expose sensitive data.
### Performance
- Consider performance implications.
- Avoid unnecessary computations.
- Use appropriate data structures.
- Add caching where beneficial.
---
## Feature Categories
### API Features
- Define clear endpoint contracts.
- Follow REST/GraphQL conventions.
- Include proper validation.
- Document request/response schemas.
### UI Features
- Follow design system patterns.
- Ensure accessibility (a11y).
- Support internationalization (i18n).
- Handle loading and error states.
### Backend Features
- Design for scalability.
- Consider data migration needs.
- Handle edge cases gracefully.
- Add appropriate logging.
### Integration Features
- Define clear interfaces.
- Handle external service failures.
- Add retry logic where appropriate.
- Document integration requirements.
---
## Non-Goals
This agent must NOT:
- Implement features beyond the defined scope
- Fix unrelated bugs (create separate issues)
- Refactor existing code unrelated to the feature
- Skip test coverage
- Ignore existing patterns and conventions
- Make breaking changes without explicit approval
---
## Success Criteria
A successful feature implementation results in:
- Fully functional feature matching requirements
- Comprehensive test coverage
- Passing CI (tests, lint, TypeScript)
- Clear documentation
- Easy-to-review Pull Request
- No regressions in existing functionality
- Ready for production deployment

261
.github/agents/refactor-agent.md vendored Normal file
View File

@@ -0,0 +1,261 @@
---
name: Refactor Agent
description: |
A disciplined agent that performs code refactoring with a focus on improving code quality,
maintainability, and readability without changing external behavior. It ensures all tests
pass before and after changes, and creates incremental, reviewable PRs.
---
# Refactor Agent
## Purpose
This agent performs controlled refactoring operations to improve code quality.
Its goal is to:
- Improve code readability, maintainability, and structure
- Preserve existing behavior (no functional changes)
- Ensure all quality gates pass throughout the process
- Create incremental, easy-to-review changes
- Document the rationale behind refactoring decisions
The agent must **not introduce new features, fix bugs, or change external behavior**.
---
## Operating Principles
1. **Behavior Preservation**
- External behavior must remain identical before and after refactoring.
- All existing tests must continue to pass.
- If tests fail, the refactoring approach must be reconsidered.
2. **Incremental Changes**
- Break large refactors into smaller, atomic commits.
- Each commit should be independently valid and reviewable.
- Prefer multiple small PRs over one large PR when appropriate.
3. **Quality Gates Are Mandatory**
- All existing tests must pass.
- Lint must pass with no new warnings or errors.
- TypeScript type checking must pass without errors.
- Build must succeed.
4. **Clear Rationale**
- Every refactoring decision must have a documented reason.
- Common reasons include: reducing duplication, improving type safety, enhancing readability, simplifying complexity.
5. **Scope Discipline**
- Stay focused on the refactoring goal.
- Do not fix unrelated bugs discovered during refactoring.
- Do not add new features or optimizations.
- Document discovered problems as TODOs for future issues (see Section: Documenting Out-of-Scope Findings).
---
## Documenting Out-of-Scope Findings
When you discover bugs, technical debt, or improvement opportunities outside the current refactoring scope, **do not fix them**. Instead, create a detailed TODO comment or document them in the PR description so they can become separate issues.
### TODO Format
Add a TODO comment in the code near where the problem was found.
**Type prefixes** (same as PR conventions):
- `bug` - A bug that needs to be fixed
- `feat` - A new feature opportunity
- `refactor` - Code that needs refactoring
- `chore` - Maintenance tasks (dependencies, configs, etc.)
- `test` - Missing or incomplete tests
**Optional labels** (GitHub labels in brackets):
- `[security]` - Security-related issues
- `[performance]` - Performance improvements
- `[a11y]` - Accessibility issues
- `[i18n]` - Internationalization issues
- `[breaking]` - Breaking changes
- Any other GitHub label relevant to the issue
```typescript
// TODO: type [optional-label] <Brief title>
// Problem: <Detailed description of what is wrong>
// Location: <File path and function/component name>
// Impact: <How this affects the system - severity, affected features>
// Suggested fix: <High-level approach to resolve>
// Discovered while: <Reference to current PR/issue>
```
### Example
```typescript
// TODO: chore [breaking] Deprecated API usage in notification service
// Problem: The notifyUser() function uses the deprecated Meteor.defer() API
// which will be removed in the next major version.
// Location: apps/meteor/server/services/notifications/notifyUser.ts:45
// Impact: High - Will break notifications after Meteor upgrade
// Suggested fix: Replace with Promise-based async/await pattern using
// the new queueMicrotask() or setImmediate() alternatives.
// Discovered while: Refactoring notification module structure
```
### In PR Description
Also list discovered issues in the PR description under a "Discovered Issues" section:
```markdown
## Discovered Issues (Out of Scope)
The following issues were discovered during this refactoring and should be addressed in separate PRs:
- `chore` [breaking]: **Deprecated API usage** - See TODO in `notifyUser.ts:45`
- `bug`: **Missing error boundary** - See TODO in `MessageList.tsx:23`
- `bug` [performance]: **Potential memory leak** - See TODO in `subscriptionManager.ts:112`
```
---
## Step-by-Step Execution Flow
### 1. Understand the Refactoring Goal
- Clearly define what needs to be improved:
- Code duplication?
- Complex conditionals?
- Poor naming?
- Missing type safety?
- Tight coupling?
- Large files/functions?
- Identify the scope and boundaries of the refactoring.
---
### 2. Analyze Current State
- Review the existing code structure.
- Identify:
- Existing test coverage
- Dependencies and dependents
- Potential risk areas
- Document the current state for reference.
---
### 3. Ensure Test Coverage
- Verify existing tests adequately cover the code being refactored.
- If coverage is insufficient:
- Add characterization tests that capture current behavior.
- These tests act as a safety net during refactoring.
- Tests must pass before any refactoring begins.
---
### 4. Plan the Refactoring Steps
- Break down the refactoring into discrete steps.
- Each step should:
- Be independently verifiable
- Maintain a working codebase
- Be easy to review
- Order steps to minimize risk.
---
### 5. Execute Refactoring Incrementally
For each step:
1. Make the targeted change.
2. Run tests to verify behavior preservation.
3. Run lint and type checking.
4. Commit with a clear message explaining the change.
Common refactoring patterns to apply:
- **Extract Function/Method**: Break down large functions
- **Rename**: Improve clarity of names
- **Move**: Relocate code to better locations
- **Inline**: Remove unnecessary abstractions
- **Extract Interface/Type**: Improve type definitions
- **Consolidate Duplicates**: DRY principle application
- **Simplify Conditionals**: Reduce complexity
---
### 6. Validate Final State
After all refactoring steps:
- All tests pass.
- Lint passes.
- TypeScript compilation passes.
- Build succeeds.
- Code review checklist:
- Is the code more readable?
- Is the code more maintainable?
- Is the structure improved?
- Are there any regressions?
---
### 7. Open the Pull Request
The PR must:
- Clearly describe the refactoring goal and rationale.
- List the refactoring patterns applied.
- Confirm that no behavioral changes were introduced.
- Reference any related issues or technical debt items.
- Include before/after examples if helpful.
---
## Refactoring Categories
### Structural Refactoring
- File/folder reorganization
- Module extraction
- Dependency restructuring
### Code Quality Refactoring
- Naming improvements
- Function decomposition
- Duplication removal
- Complexity reduction
### Type Safety Refactoring
- Adding explicit types
- Removing `any` types
- Improving generic usage
- Adding type guards
### Pattern Application
- Applying design patterns
- Removing anti-patterns
- Standardizing approaches
---
## Non-Goals
This agent must NOT:
- Change external behavior
- Fix bugs (create separate issues)
- Add new features
- Optimize performance (unless part of explicit refactoring goal)
- Make changes outside the defined scope
- Skip quality gate verification
---
## Success Criteria
A successful refactoring results in:
- Improved code quality metrics (readability, maintainability)
- All tests passing (no behavioral changes)
- Passing CI (tests, lint, TypeScript)
- Clear documentation of changes
- Easy-to-review Pull Request
- No new bugs introduced

21
.github/bot-config.yml vendored Normal file
View File

@@ -0,0 +1,21 @@
bot:
name: "@rocket-cat"
whitelist:
users:
- wreiske
- TwizzyDizzy
- theorenck
- JSzaszvari
- reetp
labels:
- "Contributions: welcome"
- "Contributions: only core team"
- "Feature: Request"
- "Feature: Planned"
- "type: bug"
- "help wanted"
- duplicate
- enhancement
- invalid
- question
- wontfix

30
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
version: 2
updates:
# Main repo NPM package
- package-ecosystem: npm
directory: '/'
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- 'automerge'
## EE dependencies
- package-ecosystem: npm
directory: '/ee/server/services'
schedule:
interval: daily
open-pull-requests-limit: 10
labels:
- 'automerge'
# Maintain dependencies for GitHub Actions
- package-ecosystem: 'github-actions'
directory: '/'
schedule:
interval: 'daily'
groups:
# CodeQL steps must all run the same version, so they have to be bumped together
codeql-action:
patterns:
- 'github/codeql-action*'

221
.github/history-manual.json vendored Normal file
View File

@@ -0,0 +1,221 @@
{
"0.55.0": [{
"title": "[BREAK] `getUsersOfRoom` API to return array of objects with user and username, instead of array of strings",
"userLogin": "rodrigok",
"contributors": []
}, {
"title": "[FIX] Incoming integrations would break when trying to use the `Store` feature.`",
"userLogin": "rodrigok",
"contributors": []
}, {
"title": "[FIX] Removed Deprecated Package rocketchat:sharedsecret`",
"userLogin": "rodrigok",
"contributors": []
}],
"0.72.0-rc.0": [{
"title": "[BREAK] Support for Cordova (Rocket.Chat Legacy app) has reached End-of-life, support has been discontinued",
"userLogin": "sampaiodiego",
"contributors": []
}],
"3.0.0-rc.9": [{
"title": "[BREAK] TLS v1.0 and TLS v1.1 were disabled by due to NodeJS update to v12. You can still enable them by using flags like `--tls-min-v1.0` and `--tls-min-v1.1`",
"userLogin": "sampaiodiego",
"contributors": []
}],
"3.6.0-rc.0": [{
"pr": "18642",
"title": "[NEW] Admin option to reset other users’ E2E encryption key",
"userLogin": "rodrigok",
"contributors": [],
"description": "Requires the 2FA password fallback enforcement enabled to work"
}],
"3.7.3": [{
"title": "[FIX] Exception on certain login cases including SAML",
"userLogin": "sampaiodiego",
"contributors": [
"sampaiodiego"
]
}],
"3.8.3": [{
"title": "[FIX] Exception on certain login cases including SAML",
"userLogin": "sampaiodiego",
"contributors": [
"sampaiodiego"
]
}],
"3.9.1": [{
"title": "[FIX] Exception on certain login cases including SAML",
"userLogin": "sampaiodiego",
"contributors": [
"sampaiodiego"
]
}],
"3.10.5": [{
"title": "[FIX] Security Hotfix",
"userLogin": "sampaiodiego",
"contributors": [
"sampaiodiego"
]
}],
"3.12.0-rc.3": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "sampaiodiego",
"contributors": [
"sampaiodiego"
]
}],
"3.12.2": [{
"title": "[FIX] Bump Livechat widget",
"userLogin": "sampaiodiego",
"contributors": [
"sampaiodiego"
]
}, {
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "sampaiodiego",
"contributors": [
"sampaiodiego",
"g-thome",
"KevLehman",
"matheusbsilva137"
]
}],
"3.13.2": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "sampaiodiego",
"contributors": [
"sampaiodiego",
"KevLehman",
"renatobecker"
]
}],
"3.14.2": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "sampaiodiego",
"contributors": [
"sampaiodiego",
"KevLehman",
"g-thome"
]
}],
"3.14.4": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "ggazzo",
"contributors": [
"ggazzo"
]
}],
"3.16.3": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "sampaiodiego",
"contributors": [
"g-thome",
"ggazzo",
"sampaiodiego",
"matheusbsilva137",
"pierre-lehnen-rc"
]
}],
"3.18.2": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "sampaiodiego",
"contributors": [
"sampaiodiego",
"pierre-lehnen-rc"
]
}],
"3.18.6": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "d-gubert",
"contributors": [
"ggazzo"
]
}],
"3.18.7": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "d-gubert",
"contributors": [
"ggazzo"
]
}],
"4.1.1": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "sampaiodiego",
"contributors": [
"sampaiodiego"
]
}],
"4.3.2": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "sampaiodiego",
"contributors": [
"sampaiodiego",
"yash-rajpal",
"pierre-lehnen-rc",
"gronke"
]
}],
"4.3.3": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "sampaiodiego",
"contributors": [
"gronke"
]
}],
"4.4.4": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "d-gubert",
"contributors": [
"ggazzo"
]
}],
"4.4.5": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "d-gubert",
"contributors": [
"ggazzo"
]
}],
"4.7.3": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "d-gubert",
"contributors": [
"ggazzo"
]
}],
"4.7.4": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "d-gubert",
"contributors": [
"ggazzo"
]
}],
"4.8.2": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "sampaiodiego",
"contributors": [
"sampaiodiego"
]
}],
"5.1.2": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "ggazzo",
"contributors": [
"ggazzo"
]
}],
"5.3.3": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "ggazzo",
"contributors": [
"ggazzo"
]
}],
"5.4.3": [{
"title": "[FIX] Security Hotfix (https://docs.rocket.chat/guides/security/security-updates)",
"userLogin": "ggazzo",
"contributors": [
"ggazzo"
]
}]
}

29
.github/issue-close-app.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
# Config for Close Issue app: https://probot.github.io/apps/close-issue/
# Comment that will be sent if an issue is judged to be closed
comment: |
This issue was closed because it does not use our bug report issue template.
Please make sure to use it and fill it as much as you can so we can provide better and faster support.
The following sections **must not** be removed, or else the BOT will close it immediately again:
* Steps to reproduce
* Expected behavior
* Actual behavior
* Server Setup Information
* Version of Rocket.Chat Server
issueConfigs:
# There can be several configs for different kind of issues.
- content:
# Bug report
- "Steps to reproduce"
- "Expected behavior"
- "Actual behavior"
- "Server Setup Information"
- "Version of Rocket.Chat Server"
- content:
# Release issue
- "Before Release - Preparation"
# The issue is considered to be valid if it includes all keywords from any of these two configs.
# Or it will be closed by the app.

View File

@@ -0,0 +1,33 @@
name: Auto-close duplicate issues
on:
schedule:
- cron: '0 9 * * *'
workflow_dispatch:
permissions: {}
jobs:
auto-close-duplicates:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: latest
- name: Auto-close duplicate issues
run: bun run scripts/auto-close-duplicates.ts
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}
GITHUB_REPOSITORY_NAME: ${{ github.event.repository.name }}
STATSIG_API_KEY: ${{ secrets.STATSIG_API_KEY }}

128
.github/workflows/ci-code-check.yml vendored Normal file
View File

@@ -0,0 +1,128 @@
name: Code Checks
on:
workflow_call:
inputs:
node-version:
required: true
type: string
deno-version:
required: true
type: string
env:
TOOL_NODE_FLAGS: ${{ vars.TOOL_NODE_FLAGS }}
permissions: {}
jobs:
code-check:
runs-on: ubuntu-24.04-arm
permissions:
contents: read
name: ${{ matrix.check == 'ts' && 'TypeScript' || 'Code Lint' }}
strategy:
fail-fast: false
matrix:
check: ['ts', 'lint']
steps:
- name: Set Swap Space
uses: pierotofy/set-swap-space@49819abfb41bd9b44fb781159c033dba90353a7c # v1.0.0
with:
swap-size-gb: 4
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup NodeJS
uses: ./.github/actions/setup-node
with:
node-version: ${{ inputs.node-version }}
deno-version: ${{ inputs.deno-version }}
cache-modules: true
install: true
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- uses: rharkor/caching-for-turbo@2238fae6eb9a9936f92356f54cb3660200d105e7 # v2.5.1
- uses: ./.github/actions/restore-packages
- name: Restore TypeScript incremental cache
id: restore-typecheck
if: matrix.check == 'ts'
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ./apps/meteor/tsconfig.typecheck.tsbuildinfo
key: typecheck-cache-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
restore-keys: |
typecheck-cache-${{ runner.os }}-
- name: Cache observability (typecheck)
if: matrix.check == 'ts'
run: |
{
echo "### TypeScript incremental cache"
echo "- **exact hit**: \`${{ steps.restore-typecheck.outputs.cache-hit }}\`"
} >> "$GITHUB_STEP_SUMMARY"
- name: Install Meteor
shell: bash
run: |
# Restore bin from cache
set +e
METEOR_SYMLINK_TARGET=$(readlink ~/.meteor/meteor)
METEOR_TOOL_DIRECTORY=$(dirname "$METEOR_SYMLINK_TARGET")
set -e
LAUNCHER=$HOME/.meteor/$METEOR_TOOL_DIRECTORY/scripts/admin/launch-meteor
if [ -e "$LAUNCHER" ]
then
echo "Cached Meteor bin found, restoring it"
sudo cp "$LAUNCHER" "/usr/local/bin/meteor"
else
echo "No cached Meteor bin found."
fi
# only install meteor if bin isn't found
command -v meteor >/dev/null 2>&1 || curl https://install.meteor.com | sed s/--progress-bar/-sL/g | /bin/sh
- name: TS TypeCheck
if: matrix.check == 'ts'
run: yarn turbo run typecheck --concurrency=5
- name: Save TypeScript incremental cache
if: matrix.check == 'ts' && github.ref == 'refs/heads/develop' && github.event_name == 'push'
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ./apps/meteor/tsconfig.typecheck.tsbuildinfo
key: typecheck-cache-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
- name: Restore ESLint cache
id: restore-eslint
if: matrix.check == 'lint'
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ./apps/meteor/.eslintcache
key: eslintcache-${{ runner.os }}-${{ hashFiles('yarn.lock') }}
restore-keys: |
eslintcache-${{ runner.os }}-
- name: Cache observability (eslint)
if: matrix.check == 'lint'
run: |
{
echo "### ESLint cache"
echo "- **exact hit**: \`${{ steps.restore-eslint.outputs.cache-hit }}\`"
} >> "$GITHUB_STEP_SUMMARY"
- name: Lint
if: matrix.check == 'lint'
run: yarn lint
- name: Save ESLint cache
if: matrix.check == 'lint' && github.ref == 'refs/heads/develop' && github.event_name == 'push'
uses: actions/cache/save@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
with:
path: ./apps/meteor/.eslintcache
key: eslintcache-${{ runner.os }}-${{ hashFiles('yarn.lock') }}

View File

@@ -0,0 +1,42 @@
# .github/workflows/ci-preview-deploy.yml
name: Deploy GitHub Pages
concurrency: preview-deploy-${{ github.ref }}
on:
push:
branches:
- main
- master
- develop
permissions: {}
jobs:
deploy-preview:
runs-on: ubuntu-24.04-arm
permissions:
contents: write
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: rharkor/caching-for-turbo@2238fae6eb9a9936f92356f54cb3660200d105e7 # v2.5.1
- name: Setup NodeJS
uses: ./.github/actions/setup-node
with:
cache-modules: true
install: true
- name: Build
run: |
yarn turbo run build-preview
yarn turbo run .:build-preview-move
npx indexifier .preview --html --extensions .html > .preview/index.html
mv .preview ${{ github.ref_name }}
mkdir .preview
mv ${{ github.ref_name }} .preview
- name: Deploy
uses: peaceiris/actions-gh-pages@84c30a85c19949d7eee79c4ff27748b70285e453 # v4.1.0
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: .preview
keep_files: true

344
.github/workflows/ci-test-e2e.yml vendored Normal file
View File

@@ -0,0 +1,344 @@
name: Tests E2E
on:
workflow_call:
inputs:
node-version:
required: true
type: string
deno-version:
required: true
type: string
lowercase-repo:
required: true
type: string
gh-docker-tag:
required: true
type: string
enterprise-license:
type: string
transporter:
type: string
mongodb-version:
default: "['8.0']"
required: false
type: string
release:
required: true
type: string
fips:
default: false
required: false
type: boolean
shard:
default: '[1]'
required: false
type: string
total-shard:
default: 1
required: false
type: number
retries:
default: 0
required: false
type: number
type:
required: true
type: string
coverage:
required: false
type: string
secrets:
CR_USER:
required: true
CR_PAT:
required: true
QASE_API_TOKEN:
required: false
REPORTER_ROCKETCHAT_URL:
required: false
REPORTER_ROCKETCHAT_API_KEY:
required: false
CODECOV_TOKEN:
required: false
REPORTER_JIRA_ROCKETCHAT_API_KEY:
required: false
NPM_TOKEN:
required: false
env:
MONGO_URL: mongodb://localhost:27017/rocketchat?replicaSet=rs0&directConnection=true
TOOL_NODE_FLAGS: ${{ vars.TOOL_NODE_FLAGS }}
LOWERCASE_REPOSITORY: ${{ inputs.lowercase-repo }}
DOCKER_TAG: ${{ inputs.gh-docker-tag }}-amd64
permissions: {}
jobs:
test:
runs-on: ubuntu-24.04
permissions:
actions: read
contents: read
env:
# if building for production on develop branch or release, add suffix for coverage images
DOCKER_TAG_SUFFIX_ROCKETCHAT: ${{ inputs.coverage == matrix.mongodb-version && (github.event_name == 'release' || github.ref == 'refs/heads/develop') && '-cov' || '' }}
MONGODB_VERSION: ${{ matrix.mongodb-version }}
COVERAGE_DIR: '/tmp/coverage/${{ startsWith(inputs.type, ''api'') && ''api'' || inputs.type }}'
COVERAGE_FILE_NAME: '${{ inputs.type }}-${{ matrix.shard }}.json'
COVERAGE_REPORTER: ${{ inputs.coverage == matrix.mongodb-version && 'json' || '' }}
strategy:
fail-fast: false
matrix:
mongodb-version: ${{ fromJSON(inputs.mongodb-version) }}
shard: ${{ fromJSON(inputs.shard) }}
name: MongoDB ${{ matrix.mongodb-version }}${{ inputs.coverage == matrix.mongodb-version && ' coverage' || '' }} (${{ matrix.shard }}/${{ inputs.total-shard }})
steps:
- name: Collect Workflow Telemetry
if: inputs.type == 'perf'
uses: catchpoint/workflow-telemetry-action@94c3c3d9567a0205de6da68a76c428ce4e769af1 # v2.0.0
with:
theme: dark
job_summary: true
comment_on_pr: false
- name: Setup kernel limits
run: |
echo "500 65535" > sudo tee -a /proc/sys/net/ipv4/ip_local_port_range
sudo sysctl -w net.ipv4.tcp_mem="383865 511820 2303190"
echo fs.file-max=20000500 | sudo tee -a /etc/sysctl.conf
echo fs.nr_open=20000500 | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
- name: Login to GitHub Container Registry
if: (github.event.pull_request.head.repo.full_name == github.repository || github.event_name == 'release' || github.ref == 'refs/heads/develop') && github.actor != 'dependabot[bot]'
uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
with:
registry: ghcr.io
username: ${{ secrets.CR_USER }}
password: ${{ secrets.CR_PAT }}
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup NodeJS
uses: ./.github/actions/setup-node
with:
node-version: ${{ inputs.node-version }}
deno-version: ${{ inputs.deno-version }}
cache-modules: true
install: true
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- uses: rharkor/caching-for-turbo@2238fae6eb9a9936f92356f54cb3660200d105e7 # v2.5.1
- uses: ./.github/actions/restore-packages
# Download Docker images from build artifacts
- name: Download Docker images
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
if: github.event.pull_request.head.repo.full_name != github.repository && github.event_name != 'release' && github.ref != 'refs/heads/develop'
with:
pattern: ${{ inputs.release == 'ce' && 'docker-image-rocketchat-amd64-coverage' || (inputs.fips && 'docker-image-*-amd64-fips' || 'docker-image-*-amd64-coverage') }}
path: /tmp/docker-images
merge-multiple: true
# Load Docker images
- name: Load Docker images
if: github.event.pull_request.head.repo.full_name != github.repository && github.event_name != 'release' && github.ref != 'refs/heads/develop'
shell: bash
run: |
set -o xtrace
# Load all downloaded images
for image_file in /tmp/docker-images/*.tar; do
if [ -f "$image_file" ]; then
echo "Loading image from $image_file"
docker load -i "$image_file"
rm "$image_file"
fi
done
# List loaded images
docker images
- name: Set DEBUG_LOG_LEVEL (debug enabled)
if: runner.debug == '1'
run: echo "DEBUG_LOG_LEVEL=2" >> "$GITHUB_ENV"
- name: Start httpbin container and wait for it to be ready
if: startsWith(inputs.type, 'api')
run: |
docker compose -f docker-compose-ci.yml up -d httpbin
- name: Prepare code coverage directory
run: |
set -o xtrace
mkdir -p "$COVERAGE_DIR"
chmod 777 "$COVERAGE_DIR"
- name: Start containers for CE
if: inputs.release == 'ce'
env:
# API tests intentionally invoke deprecated DDP methods through
# /v1/method.call/:method. TEST_MODE='api' keeps every other test
# behavior on (rate-limiter bypass, short cache TTLs) while letting
# the deprecation logger log without throwing. Other suites use the
# docker-compose default of TEST_MODE='true'.
TEST_MODE: ${{ startsWith(inputs.type, 'api') && 'api' || 'true' }}
TEST_TYPE: ${{ inputs.type }}
run: |
# when we are testing CE, we only need to start the rocketchat container (plus mock-server for the api suite)
services=(rocketchat)
if [ "$TEST_TYPE" == "api" ]; then
services+=(mock-server)
fi
DEBUG_LOG_LEVEL=${DEBUG_LOG_LEVEL:-0} docker compose -f docker-compose-ci.yml up -d "${services[@]}" --wait
- name: Start containers for EE
if: inputs.release == 'ee'
env:
ENTERPRISE_LICENSE: ${{ inputs.enterprise-license }}
TRANSPORTER: ${{ inputs.transporter }}
COMPOSE_PROFILES: ${{ inputs.type == 'api' && 'api' || '' }}
TEST_MODE: ${{ startsWith(inputs.type, 'api') && 'api' || 'true' }}
APPS_ENGINE_RUNTIME_BACKEND: ${{ inputs.type == 'api-apps-deno' && 'deno' || '' }}
FIPS_OVERRIDE: ${{ inputs.fips && '-f docker-compose-ci.fips.yml' || '' }}
run: |
read -r -a fips_override <<< "$FIPS_OVERRIDE"
DEBUG_LOG_LEVEL=${DEBUG_LOG_LEVEL:-0} docker compose -f docker-compose-ci.yml "${fips_override[@]}" up -d --wait
- uses: ./.github/actions/setup-playwright
if: inputs.type == 'ui'
- name: Wait services to start up
if: inputs.release == 'ee'
run: |
docker ps
until docker compose -f docker-compose-ci.yml logs ddp-streamer-service | grep -q "NetworkBroker started successfully"; do
echo "Waiting 'ddp-streamer' to start up"
((c++)) && ((c==10)) && docker compose -f docker-compose-ci.yml logs ddp-streamer-service && exit 1
sleep 10
done;
- name: Remove unused Docker images
run: docker system prune -af
- name: E2E Test API
if: inputs.type == 'api'
working-directory: ./apps/meteor
env:
WEBHOOK_TEST_URL: 'http://httpbin'
IS_EE: ${{ inputs.release == 'ee' && 'true' || '' }}
run: |
set -o xtrace
npm run testapi || s=$?
docker compose -f ../../docker-compose-ci.yml stop
ls -la "$COVERAGE_DIR"
exit "${s:-0}"
# This step should be temporary, only here until we remove the deno-runtime
- name: E2E Test API (apps + deno-runtime)
if: (inputs.type == 'api-apps-deno' && inputs.release == 'ee')
working-directory: ./apps/meteor
env:
WEBHOOK_TEST_URL: 'http://httpbin'
IS_EE: 'true'
run: |
set -o xtrace
npm run testapi:apps || s=$?
docker compose -f ../../docker-compose-ci.yml stop
ls -la "$COVERAGE_DIR"
exit "${s:-0}"
- name: E2E Test API (Livechat)
if: inputs.type == 'api-livechat'
working-directory: ./apps/meteor
env:
WEBHOOK_TEST_URL: 'http://httpbin'
IS_EE: ${{ inputs.release == 'ee' && 'true' || '' }}
run: |
set -o xtrace
npm run testapi:livechat || s=$?
docker compose -f ../../docker-compose-ci.yml stop
ls -la "$COVERAGE_DIR"
exit "${s:-0}"
- name: E2E Test UI (${{ matrix.shard }}/${{ inputs.total-shard }})
if: inputs.type == 'ui'
env:
E2E_COVERAGE: ${{ inputs.coverage == matrix.mongodb-version && 'true' || '' }}
IS_EE: ${{ inputs.release == 'ee' && 'true' || '' }}
REPORTER_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_ROCKETCHAT_API_KEY }}
REPORTER_ROCKETCHAT_URL: ${{ secrets.REPORTER_ROCKETCHAT_URL }}
REPORTER_JIRA_ROCKETCHAT_API_KEY: ${{ secrets.REPORTER_JIRA_ROCKETCHAT_API_KEY }}
REPORTER_ROCKETCHAT_REPORT: ${{ github.event.pull_request.draft != 'true' && secrets.REPORTER_ROCKETCHAT_URL != '' && 'true' || '' }}
REPORTER_ROCKETCHAT_RUN: ${{ github.run_number }}
REPORTER_ROCKETCHAT_BRANCH: ${{ github.ref }}
REPORTER_ROCKETCHAT_DRAFT: ${{ github.event.pull_request.draft }}
REPORTER_ROCKETCHAT_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
REPORTER_ROCKETCHAT_AUTHOR: ${{ github.event.pull_request.user.login }}
REPORTER_ROCKETCHAT_RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
REPORTER_ROCKETCHAT_PR: ${{ github.event.pull_request.number }}
QASE_API_TOKEN: ${{ secrets.QASE_API_TOKEN }}
QASE_REPORT: ${{ github.ref == 'refs/heads/develop' && 'true' || '' }}
CI: true
PLAYWRIGHT_RETRIES: ${{ inputs.retries }}
E2E_SHARD: ${{ matrix.shard }}
E2E_TOTAL_SHARD: ${{ inputs.total-shard }}
working-directory: ./apps/meteor
run: |
set -o xtrace
yarn prepare
yarn test:e2e --shard="$E2E_SHARD/$E2E_TOTAL_SHARD"
- name: Merge ui coverage files
if: inputs.type == 'ui' && inputs.coverage == matrix.mongodb-version
working-directory: ./apps/meteor
run: |
npx nyc merge .nyc_output "${COVERAGE_DIR}/${COVERAGE_FILE_NAME}"
ls -la "$COVERAGE_DIR" || true
- name: Store playwright test trace
if: inputs.type == 'ui' && always()
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: playwright-test-trace-${{ inputs.release }}${{ inputs.fips && '-fips' || '' }}-${{ matrix.mongodb-version }}-${{ matrix.shard }}
path: ./apps/meteor/tests/e2e/.playwright*
include-hidden-files: true
- name: Show server logs if E2E test failed
if: failure()
run: docker compose -f docker-compose-ci.yml logs rocketchat authorization-service queue-worker-service ddp-streamer-service account-service presence-service omnichannel-transcript-service
- name: Show mongo logs if E2E test failed
if: failure()
run: docker compose -f docker-compose-ci.yml logs mongo
- name: Show traefik logs if E2E test failed
if: failure()
run: docker compose -f docker-compose-ci.yml logs traefik
- name: Store coverage
if: inputs.coverage == matrix.mongodb-version
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: coverage-${{ inputs.type }}-${{ matrix.shard }}
path: /tmp/coverage
include-hidden-files: true

62
.github/workflows/ci-test-storybook.yml vendored Normal file
View File

@@ -0,0 +1,62 @@
name: Test Storybook
on:
workflow_call:
inputs:
node-version:
required: true
type: string
deno-version:
required: true
type: string
secrets:
CODECOV_TOKEN:
required: true
NPM_TOKEN:
required: false
env:
TOOL_NODE_FLAGS: ${{ vars.TOOL_NODE_FLAGS }}
permissions: {}
jobs:
test:
runs-on: ubuntu-24.04-arm
permissions:
contents: read
name: Test Storybook
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup NodeJS
uses: ./.github/actions/setup-node
with:
node-version: ${{ inputs.node-version }}
deno-version: ${{ inputs.deno-version }}
cache-modules: true
install: true
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- uses: rharkor/caching-for-turbo@2238fae6eb9a9936f92356f54cb3660200d105e7 # v2.5.1
- uses: ./.github/actions/restore-packages
- uses: ./.github/actions/setup-playwright
- name: Run tests
run: yarn test-storybook
env:
STORYBOOK_DISABLE_TELEMETRY: 1
- uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
flags: unit
verbose: true
token: ${{ secrets.CODECOV_TOKEN }}
# tests don't re-run on the develop push, so the merge queue run (same SHA
# that lands on develop) provides the develop coverage baseline
override_branch: ${{ github.event_name == 'merge_group' && github.event.merge_group.base_ref == 'refs/heads/develop' && 'develop' || '' }}

62
.github/workflows/ci-test-unit.yml vendored Normal file
View File

@@ -0,0 +1,62 @@
name: Tests Unit
on:
workflow_call:
inputs:
node-version:
required: true
type: string
deno-version:
required: true
type: string
enterprise-license:
required: false
type: string
secrets:
CODECOV_TOKEN:
required: false
NPM_TOKEN:
required: false
env:
MONGO_URL: mongodb://localhost:27017/rocketchat?replicaSet=rs0&directConnection=true
TOOL_NODE_FLAGS: ${{ vars.TOOL_NODE_FLAGS }}
ENTERPRISE_LICENSE: ${{ inputs.enterprise-license }}
permissions: {}
jobs:
test:
runs-on: ubuntu-24.04-arm
permissions:
contents: read
name: Unit Tests
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup NodeJS
uses: ./.github/actions/setup-node
with:
node-version: ${{ inputs.node-version }}
deno-version: ${{ inputs.deno-version }}
cache-modules: true
install: true
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- uses: rharkor/caching-for-turbo@2238fae6eb9a9936f92356f54cb3660200d105e7 # v2.5.1
- uses: ./.github/actions/restore-packages
- name: Unit Test
run: yarn testunit --concurrency=1
- uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0
with:
flags: unit
verbose: true
token: ${{ secrets.CODECOV_TOKEN }}
# tests don't re-run on the develop push, so the merge queue run (same SHA
# that lands on develop) provides the develop coverage baseline
override_branch: ${{ github.event_name == 'merge_group' && github.event.merge_group.base_ref == 'refs/heads/develop' && 'develop' || '' }}

1333
.github/workflows/ci.yml vendored Normal file

File diff suppressed because it is too large Load Diff

57
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,57 @@
name: 'Code scanning - action'
on:
push:
branches-ignore:
- dependabot/**
pull_request:
schedule:
- cron: '0 13 * * *'
jobs:
CodeQL-Build:
# CodeQL runs on ubuntu-latest and windows-latest
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
fetch-depth: 2
# If this run was triggered by a pull request event, then checkout
# the head of the pull request instead of the merge commit.
- run: git checkout HEAD^2
if: ${{ github.event_name == 'pull_request' }}
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
# Override language selection by uncommenting this and choosing your languages
with:
languages: javascript
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4
# ℹ️ Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@f205ea1c3313d32999d8d6a48b4f6530d4437b38 # v4.37.4

85
.github/workflows/dedupe-issues.yml vendored Normal file
View File

@@ -0,0 +1,85 @@
name: Rocket.Chat Issue Dedupe
on:
issues:
types: [opened]
workflow_dispatch:
inputs:
issue_number:
description: 'Issue number to process for duplicate detection'
required: true
type: string
permissions: {}
jobs:
dedupe-issues:
runs-on: ubuntu-latest
timeout-minutes: 30
permissions:
contents: read
issues: write
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Run Claude Code slash command
uses: anthropics/claude-code-base-action@e8132bc5e637a42c27763fc757faa37e1ee43b34 # v0.0.63beta
with:
prompt: '/dedupe ${{ github.repository }}/issues/${{ github.event.issue.number || inputs.issue_number }}'
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
model: 'claude-sonnet-4-5-20250929'
claude_env: |
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Log duplicate comment event to Statsig
if: always()
env:
STATSIG_API_KEY: ${{ secrets.STATSIG_API_KEY }}
run: |
ISSUE_NUMBER=${{ github.event.issue.number || inputs.issue_number }}
REPO=${{ github.repository }}
if [ -z "$STATSIG_API_KEY" ]; then
echo "STATSIG_API_KEY not found, skipping Statsig logging"
exit 0
fi
# Prepare the event payload
EVENT_PAYLOAD=$(jq -n \
--arg issue_number "$ISSUE_NUMBER" \
--arg repo "$REPO" \
--arg triggered_by "${{ github.event_name }}" \
--arg actor "${{ github.actor }}" \
'{
events: [{
eventName: "github_duplicate_comment_added",
value: 1,
metadata: {
repository: $repo,
issue_number: ($issue_number | tonumber),
triggered_by: $triggered_by,
workflow_run_id: "${{ github.run_id }}",
actor: $actor
},
time: (now | floor | tostring)
}]
}')
# Send to Statsig API
echo "Logging duplicate comment event to Statsig for issue #${ISSUE_NUMBER}"
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST https://events.statsigapi.net/v1/log_event \
-H "Content-Type: application/json" \
-H "STATSIG-API-KEY: ${STATSIG_API_KEY}" \
-d "$EVENT_PAYLOAD")
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
BODY=$(echo "$RESPONSE" | head -n-1)
if [ "$HTTP_CODE" -eq 200 ] || [ "$HTTP_CODE" -eq 202 ]; then
echo "Successfully logged duplicate comment event for issue #${ISSUE_NUMBER}"
else
echo "Failed to log duplicate comment event for issue #${ISSUE_NUMBER}. HTTP ${HTTP_CODE}: ${BODY}"
fi

View File

@@ -0,0 +1,42 @@
name: 'Release PR Description'
on:
pull_request:
branches:
- master
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions: {}
jobs:
update-pr:
runs-on: ubuntu-24.04
if: startsWith(github.head_ref, 'release-')
permissions:
contents: read
steps:
- name: Checkout Repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
token: ${{ secrets.CI_PAT }}
- name: Setup NodeJS
uses: ./.github/actions/setup-node
with:
cache-modules: true
install: true
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- uses: rharkor/caching-for-turbo@2238fae6eb9a9936f92356f54cb3660200d105e7 # v2.5.1
- name: Build packages
run: yarn build
- name: Update PR description
uses: ./packages/release-action
with:
action: update-pr-description
env:
GITHUB_TOKEN: ${{ secrets.CI_PAT }}

79
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,79 @@
name: Release
# Single entry point for every path that publishes to npm. npm allows one trusted
# publisher per package and validates the entry-point workflow filename, so `cut`,
# `next` and `publish-final` all have to run from this file.
on:
push:
branches:
- master
schedule:
- cron: '28 21 20 * *' # run at minute 28 to avoid the chance of delay due to high load on GH
workflow_dispatch:
inputs:
name:
type: choice
description: Release type
default: next
required: true
options:
- next
- patch
- cut
base-ref:
description: Base version
default: develop
required: false
concurrency: ${{ github.workflow }}-${{ github.ref }}
env:
HUSKY: 0
permissions: {}
jobs:
release:
name: Release
runs-on: ubuntu-24.04
permissions:
contents: read
id-token: write # npm trusted publishing (OIDC)
steps:
- name: Checkout Repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event_name == 'schedule' && github.ref_name || github.event_name == 'workflow_dispatch' && inputs.base-ref || '' }}
fetch-depth: 0
token: ${{ secrets.CI_PAT }}
- name: Setup NodeJS
uses: ./.github/actions/setup-node
with:
cache-modules: true
install: true
# Transitional: npm attempts the OIDC exchange first and overrides this token on
# success, so it only takes effect when the exchange fails. That keeps releases
# alive while packages are registered as trusted publishers one by one. Remove
# once every package reports a non-null dist.attestations — see docs/npm-publishing.md.
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
# Node 22 bundles npm 10, trusted publishing needs >= 11.5.1
- name: Setup npm
run: |
npm install -g npm@^11.15.0
npm --version
- uses: rharkor/caching-for-turbo@2238fae6eb9a9936f92356f54cb3660200d105e7 # v2.5.1
- name: Build packages
run: yarn build
- name: Release
uses: ./packages/release-action
with:
action: ${{ github.event_name == 'push' && 'publish-final' || github.event_name == 'schedule' && 'next' || inputs.name }}
base-ref: ${{ github.event_name == 'schedule' && github.ref_name || github.event_name == 'workflow_dispatch' && inputs.base-ref || '' }}
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }} # transitional, see the Setup NodeJS step
GITHUB_TOKEN: ${{ secrets.CI_PAT }}

20
.github/workflows/stale.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: Close inactive issues
on:
schedule:
- cron: '0 */6 * * *'
jobs:
close-issues:
runs-on: ubuntu-24.04
permissions:
issues: write
steps:
- uses: actions/stale@4391f3da665fdf50b6810c1a66712fb9ba21aa93 # v11.0.0
with:
days-before-issue-stale: 14
days-before-issue-close: 14
any-of-labels: 'stat: need more info,stat: waiting response'
stale-issue-label: 'stat: no response'
stale-issue-message: 'This issue has been marked as stale because there has been no further activity in the last 10 days. If the issue remains stale for the next 4 days (a total of 14 days with no activity), then it will be assumed that the question has been resolved and the issue will be automatically closed.'
close-issue-message: 'This issue was closed because it has been inactive for 14 days since being marked as stale.'
repo-token: ${{ secrets.GITHUB_TOKEN }}

58
.github/workflows/todo.yml vendored Normal file
View File

@@ -0,0 +1,58 @@
name: Create issues from TODOs
on:
workflow_dispatch:
inputs:
importAll:
default: false
required: false
type: boolean
description: Enable, if you want to import all TODOs. Runs on checked out branch! Only use if you're sure what you are doing.
sha:
default: ''
required: false
type: string
description: 'A commit SHA or range (e.g. "abc123" or "abc123...def456"). Single SHA compares against its parent.'
path:
default: ''
required: false
type: string
description: 'Import TODOs from a specific path (e.g. "apps/meteor/client" or "packages/core-typings/src/IMessage.ts").'
push:
branches: # do not set multiple branches, todos might be added and then get referenced by themselves in case of a merge
- develop
permissions:
issues: write
repository-projects: read
contents: read
jobs:
todos:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Setup Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: latest
- name: Install dependencies
run: bun install --frozen-lockfile
working-directory: scripts/todo-issue
- name: Create issues from TODOs
run: bun run src/index.ts
working-directory: scripts/todo-issue
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}
GITHUB_REPOSITORY_NAME: ${{ github.event.repository.name }}
GITHUB_SHA: ${{ github.sha }}
BEFORE_SHA: ${{ github.event.before }}
IMPORT_ALL: ${{ inputs.importAll || 'false' }}
SHA_INPUT: ${{ inputs.sha || '' }}
PATH_FILTER: ${{ inputs.path || '' }}

View File

@@ -0,0 +1,47 @@
name: Update Version Durability
on:
workflow_dispatch:
workflow_call:
inputs:
LTS_VERSIONS:
required: false
type: string
secrets:
CI_PAT:
required: true
D360_TOKEN:
required: true
D360_USER_ID:
required: true
permissions: {}
jobs:
update-versions:
runs-on: ubuntu-24.04
permissions:
contents: read
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- name: Use Node.js
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 24.15.0
- name: Install dependencies
run: |
cd ./.github/actions/update-version-durability
npm install
- name: Update Version Durability
uses: ./.github/actions/update-version-durability
with:
LTS_VERSIONS: ${{ inputs.LTS_VERSIONS != '' && inputs.LTS_VERSIONS || vars.LTS_VERSIONS }}
GH_TOKEN: ${{ secrets.CI_PAT }}
D360_TOKEN: ${{ secrets.D360_TOKEN }}
D360_ARTICLE_ID: 800f8d52-409d-478d-b560-f82a2c0eb7fb
D360_USER_ID: ${{ secrets.D360_USER_ID }}
PUBLISH: true

64
.gitignore vendored Normal file
View File

@@ -0,0 +1,64 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
node_modules
.pnp
.pnp.js
# testing
coverage
# next.js
.next/
out/
build
dist
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
storybook-static
# turbo
.turbo
# yarn
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
.nvmrc
.idea/
.exrc
.history
.envrc
.preview
*.sublime-workspace
**/.vim/
data/
!**/tests/data/
registration.yaml
storybook-static
development/tempo-data/
.env

19
.gitpod/.gitpod.yml Normal file
View File

@@ -0,0 +1,19 @@
tasks:
- init: |
nvm install $(jq -r .engines.node package.json) &&
curl https://install.meteor.com/?release=$(
curl -so- https://raw.githubusercontent.com/RocketChat/Rocket.Chat/develop/apps/meteor/.meteor/release | cut -d@ -f2
) | sh &&
export PATH=$PATH:/home/gitpod/.meteor &&
yarn &&
export ROOT_URL=$(gp url 3000)
command: yarn dsv
ports:
- port: 3000
visibility: public
onOpen: open-preview
vscode:
extensions:
- esbenp.prettier-vscode

15
.gitpod/automations.yaml Normal file
View File

@@ -0,0 +1,15 @@
services:
development-server:
name: Rocket.Chat development server
description: Starts the Rocket.Chat development server (yarn dsv)
triggeredBy:
- postDevcontainerStart
- manual
commands:
start: |
yarn
yarn dsv
ready: |
export ROOT_URL=$(gitpod environment port open 3000 --name "Rocket.Chat application" | sed 's|https://||')
echo $ROOT_URL
gitpod environment port open 3000 --name "Rocket.Chat application"

74
.houston/metadata.js Normal file
View File

@@ -0,0 +1,74 @@
const { execSync } = require('child_process');
const getMongoVersion = async function({ version, git }) {
try {
const workflows = await git.show([`${ version }:.github/workflows/ci.yml`]);
const mongoMatch = workflows.match(/compatibleMongoVersions\\": \[([^\]]+)\]/);
if (!mongoMatch) {
return [];
}
return mongoMatch[1].replace(/["'\\ ]/g, '').split(',');
} catch (e) {
console.error(e);
}
return [];
};
const getNodeNpmVersions = async function({ version, git, request }) {
try {
const meteorRelease = await git.show([`${ version }:apps/meteor/.meteor/release`]);
if (!/^METEOR@(\d+\.){1,2}\d/.test(meteorRelease)) {
return {};
}
const meteorVersion = meteorRelease.replace(/\n|\s/g, '');
const requestResult = await request(`https://raw.githubusercontent.com/meteor/meteor/release/${ meteorVersion }/scripts/build-dev-bundle-common.sh`);
return {
node_version: requestResult.match(/NODE_VERSION=((?:\d+\.){2}\d+)/m)[1],
npm_version: requestResult.match(/NPM_VERSION=((?:\d+\.){2}\d+)/m)[1],
};
} catch (e) {
console.error(e);
}
return {};
};
const getAppsEngineVersion = async function({ version, git }) {
try {
const result = execSync('yarn why @rocket.chat/apps-engine --json');
const resultString = result.toString();
const match = resultString.match(/"@rocket\.chat\/meteor@workspace:apps\/meteor".*"@rocket\.chat\/apps\-engine@[^#]+#npm:([^"]+)"/);
if (match) {
return match[1];
}
} catch (e) {
console.error(e);
}
return undefined;
};
module.exports = async function({ version, git, request }) {
const mongo_versions = await getMongoVersion({ version, git });
const apps_engine_version = await getAppsEngineVersion({ version, git });
const {
node_version,
npm_version,
} = await getNodeNpmVersions({ version, git, request });
return {
node_version,
npm_version,
apps_engine_version,
mongo_versions,
};
};

View File

@@ -0,0 +1,2 @@
{{> versions}}
{{> _prs}}

View File

@@ -0,0 +1,16 @@
{{#if (or release.node_version release.npm_version release.mongo_versions)}}
### Engine versions
{{#if release.node_version}}
- Node: `{{ release.node_version }}`
{{/if}}
{{#if release.npm_version}}
- NPM: `{{ release.npm_version }}`
{{/if}}
{{#if release.mongo_versions}}
- MongoDB: `{{ join release.mongo_versions ', ' }}`
{{/if}}
{{#if release.apps_engine_version}}
- Apps-Engine: `{{ release.apps_engine_version }}`
{{/if}}
{{/if}}

20
.kodiak.toml Normal file
View File

@@ -0,0 +1,20 @@
# .kodiak.toml
version = 1
[merge]
method = "squash"
automerge_label = ["stat: ready to merge", "automerge"]
block_on_neutral_required_check_runs = true
blocking_labels = ["stat: needs QA", "Invalid PR Title", "do not merge"]
prioritize_ready_to_merge = true
[merge.message]
title = "pull_request_title"
body = "empty"
include_coauthors=true
[merge.automerge_dependencies]
versions = ["minor", "patch"]
usernames = ["dependabot"]
[approve]
auto_approve_usernames = ["dependabot"]

1
.npmrc Normal file
View File

@@ -0,0 +1 @@
engine-strict = true

12
.prettierrc Normal file
View File

@@ -0,0 +1,12 @@
{
"semi": true,
"bracketSpacing": true,
"arrowParens": "always",
"endOfLine": "lf",
"jsxSingleQuote": true,
"printWidth": 140,
"quoteProps": "consistent",
"singleQuote": true,
"trailingComma": "all",
"useTabs": true
}

1
.tool-versions Normal file
View File

@@ -0,0 +1 @@
deno 2.3.1

35
.vscode/client.code-snippets vendored Normal file
View File

@@ -0,0 +1,35 @@
{
"Storybook stories module for React component": {
"scope": "typescriptreact",
"prefix": "sbmodule",
"body": [
"import type { Meta, StoryFn } from '@storybook/react';",
"",
"import $1 from './$1';",
"",
"export default {",
"\ttitle: '$2',",
"\tcomponent: $1,",
"} satisfies Meta<typeof $1>;",
"",
"export const Example: StoryFn<typeof $1> = (args) => <$1 {...args} />;",
]
},
"Storybook meta": {
"scope": "typescriptreact",
"prefix": "sbmeta",
"body": [
"export default {",
"\ttitle: '$1',",
"\tcomponent: $2,",
"} satisfies Meta<typeof $2>;"
]
},
"Storybook story": {
"scope": "typescriptreact",
"prefix": "sbstory",
"body": [
"export const $1: StoryFn<typeof $2> = (args) => <$2 {...args} />;"
]
}
}

20
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1,20 @@
{
"typescript.tsdk": "./node_modules/typescript/lib",
"cSpell.words": [
"autotranslate",
"ciphertext",
"Contextualbar",
"fname",
"Gazzodown",
"katex",
"listbox",
"livechat",
"oauthapps",
"omnichannel",
"photoswipe",
"proxify",
"searchbox",
"tmid",
"tshow"
]
}

View File

@@ -0,0 +1,144 @@
diff --git a/dist/import.mjs b/dist/import.mjs
index 668b87f9fbf77162f4baa4b02fe3586c3a2c0b26..6b6dc85b39196597504df1a287495a24ce3c0831 100644
--- a/dist/import.mjs
+++ b/dist/import.mjs
@@ -1,31 +1,7 @@
-import {I18nProvider as $18f2051aff69b9bf$export$a54013f0d02a8f82, useLocale as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7} from "./context.mjs";
-import {useMessageFormatter as $321bc95feeb923dd$export$ec23bf898b1eed85} from "./useMessageFormatter.mjs";
-import {useLocalizedStringDictionary as $fca6afa0e843324b$export$87b761675e8eaa10, useLocalizedStringFormatter as $fca6afa0e843324b$export$f12b703ca79dfbb1} from "./useLocalizedStringFormatter.mjs";
-import {useListFormatter as $33bf17300c498528$export$a2f47a3d2973640} from "./useListFormatter.mjs";
-import {useDateFormatter as $896ba0a80a8f4d36$export$85fd5fdf27bacc79} from "./useDateFormatter.mjs";
-import {useNumberFormatter as $a916eb452884faea$export$b7a616150fdb9f44} from "./useNumberFormatter.mjs";
-import {useCollator as $325a3faab7a68acd$export$a16aca283550c30d} from "./useCollator.mjs";
-import {useFilter as $bb77f239b46e8c72$export$3274cf84b703fff} from "./useFilter.mjs";
-
-/*
- * Copyright 2020 Adobe. All rights reserved.
- * This file is licensed to you under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License. You may obtain a copy
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
- * OF ANY KIND, either express or implied. See the License for the specific language
- * governing permissions and limitations under the License.
- */
-
-
-
-
-
-
-
-
-
-export {$18f2051aff69b9bf$export$a54013f0d02a8f82 as I18nProvider, $18f2051aff69b9bf$export$43bb16f9c6d9e3f7 as useLocale, $321bc95feeb923dd$export$ec23bf898b1eed85 as useMessageFormatter, $fca6afa0e843324b$export$f12b703ca79dfbb1 as useLocalizedStringFormatter, $fca6afa0e843324b$export$87b761675e8eaa10 as useLocalizedStringDictionary, $33bf17300c498528$export$a2f47a3d2973640 as useListFormatter, $896ba0a80a8f4d36$export$85fd5fdf27bacc79 as useDateFormatter, $a916eb452884faea$export$b7a616150fdb9f44 as useNumberFormatter, $325a3faab7a68acd$export$a16aca283550c30d as useCollator, $bb77f239b46e8c72$export$3274cf84b703fff as useFilter};
-//# sourceMappingURL=module.js.map
+import {I18nProvider as $18f2051aff69b9bf$export$a54013f0d02a8f82, useLocale as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7} from "./context.module.js";
+import {useLocalizedStringDictionary as $fca6afa0e843324b$export$87b761675e8eaa10, useLocalizedStringFormatter as $fca6afa0e843324b$export$f12b703ca79dfbb1} from "./useLocalizedStringFormatter.module.js";
+import {useNumberFormatter as $a916eb452884faea$export$b7a616150fdb9f44} from "./useNumberFormatter.module.js";
+import {useCollator as $325a3faab7a68acd$export$a16aca283550c30d} from "./useCollator.module.js";
+import {useFilter as $bb77f239b46e8c72$export$3274cf84b703fff} from "./useFilter.module.js";
+// Slim barrel: removed useDateFormatter (@internationalized/date ~40KB) and useMessageFormatter (@formatjs ~62KB)
+export {$18f2051aff69b9bf$export$a54013f0d02a8f82 as I18nProvider, $18f2051aff69b9bf$export$43bb16f9c6d9e3f7 as useLocale, $fca6afa0e843324b$export$f12b703ca79dfbb1 as useLocalizedStringFormatter, $fca6afa0e843324b$export$87b761675e8eaa10 as useLocalizedStringDictionary, $a916eb452884faea$export$b7a616150fdb9f44 as useNumberFormatter, $325a3faab7a68acd$export$a16aca283550c30d as useCollator, $bb77f239b46e8c72$export$3274cf84b703fff as useFilter};
diff --git a/dist/main.js b/dist/main.js
index 62b1f5e2054df93a1f3e851f191c42441cf33699..820e10e6bf275b396a46e26a8e80f46b59bffb5c 100644
--- a/dist/main.js
+++ b/dist/main.js
@@ -1,45 +1,13 @@
var $47fa5ec5ff482271$exports = require("./context.main.js");
-var $c376aa482226bf60$exports = require("./useMessageFormatter.main.js");
-var $fc53663969a3d00a$exports = require("./useLocalizedStringFormatter.main.js");
-var $cb6a3e7d490e97a4$exports = require("./useListFormatter.main.js");
-var $b80c530ff2e20243$exports = require("./useDateFormatter.main.js");
-var $fea93c5b7c90d9f4$exports = require("./useNumberFormatter.main.js");
-var $27a5ce66022270ad$exports = require("./useCollator.main.js");
-var $832d079b867c7223$exports = require("./useFilter.main.js");
-
-
-function $parcel$export(e, n, v, s) {
- Object.defineProperty(e, n, {get: v, set: s, enumerable: true, configurable: true});
-}
-
-$parcel$export(module.exports, "I18nProvider", () => $47fa5ec5ff482271$exports.I18nProvider);
-$parcel$export(module.exports, "useLocale", () => $47fa5ec5ff482271$exports.useLocale);
-$parcel$export(module.exports, "useMessageFormatter", () => $c376aa482226bf60$exports.useMessageFormatter);
-$parcel$export(module.exports, "useLocalizedStringFormatter", () => $fc53663969a3d00a$exports.useLocalizedStringFormatter);
-$parcel$export(module.exports, "useLocalizedStringDictionary", () => $fc53663969a3d00a$exports.useLocalizedStringDictionary);
-$parcel$export(module.exports, "useListFormatter", () => $cb6a3e7d490e97a4$exports.useListFormatter);
-$parcel$export(module.exports, "useDateFormatter", () => $b80c530ff2e20243$exports.useDateFormatter);
-$parcel$export(module.exports, "useNumberFormatter", () => $fea93c5b7c90d9f4$exports.useNumberFormatter);
-$parcel$export(module.exports, "useCollator", () => $27a5ce66022270ad$exports.useCollator);
-$parcel$export(module.exports, "useFilter", () => $832d079b867c7223$exports.useFilter);
-/*
- * Copyright 2020 Adobe. All rights reserved.
- * This file is licensed to you under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License. You may obtain a copy
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
- * OF ANY KIND, either express or implied. See the License for the specific language
- * governing permissions and limitations under the License.
- */
-
-
-
-
-
-
-
-
-
-//# sourceMappingURL=main.js.map
+var $fc53663969a3d00a$exports = require("./useLocalizedStringFormatter.main.js");
+var $8c5e0e4c6ca34e89$exports = require("./useNumberFormatter.main.js");
+var $22f23e74d8a5e30d$exports = require("./useCollator.main.js");
+var $7d0e351af20babe4$exports = require("./useFilter.main.js");
+// Slim barrel: removed useDateFormatter, useMessageFormatter, useListFormatter
+exports.I18nProvider = $47fa5ec5ff482271$exports.I18nProvider;
+exports.useLocale = $47fa5ec5ff482271$exports.useLocale;
+exports.useLocalizedStringFormatter = $fc53663969a3d00a$exports.useLocalizedStringFormatter;
+exports.useLocalizedStringDictionary = $fc53663969a3d00a$exports.useLocalizedStringDictionary;
+exports.useNumberFormatter = $8c5e0e4c6ca34e89$exports.useNumberFormatter;
+exports.useCollator = $22f23e74d8a5e30d$exports.useCollator;
+exports.useFilter = $7d0e351af20babe4$exports.useFilter;
diff --git a/dist/module.js b/dist/module.js
index fb8c9b0ce2c72d49866c95c3fd6e73cd26149775..6b6dc85b39196597504df1a287495a24ce3c0831 100644
--- a/dist/module.js
+++ b/dist/module.js
@@ -1,31 +1,7 @@
import {I18nProvider as $18f2051aff69b9bf$export$a54013f0d02a8f82, useLocale as $18f2051aff69b9bf$export$43bb16f9c6d9e3f7} from "./context.module.js";
-import {useMessageFormatter as $321bc95feeb923dd$export$ec23bf898b1eed85} from "./useMessageFormatter.module.js";
-import {useLocalizedStringDictionary as $fca6afa0e843324b$export$87b761675e8eaa10, useLocalizedStringFormatter as $fca6afa0e843324b$export$f12b703ca79dfbb1} from "./useLocalizedStringFormatter.module.js";
-import {useListFormatter as $33bf17300c498528$export$a2f47a3d2973640} from "./useListFormatter.module.js";
-import {useDateFormatter as $896ba0a80a8f4d36$export$85fd5fdf27bacc79} from "./useDateFormatter.module.js";
+import {useLocalizedStringDictionary as $fca6afa0e843324b$export$87b761675e8eaa10, useLocalizedStringFormatter as $fca6afa0e843324b$export$f12b703ca79dfbb1} from "./useLocalizedStringFormatter.module.js";
import {useNumberFormatter as $a916eb452884faea$export$b7a616150fdb9f44} from "./useNumberFormatter.module.js";
import {useCollator as $325a3faab7a68acd$export$a16aca283550c30d} from "./useCollator.module.js";
import {useFilter as $bb77f239b46e8c72$export$3274cf84b703fff} from "./useFilter.module.js";
-
-/*
- * Copyright 2020 Adobe. All rights reserved.
- * This file is licensed to you under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License. You may obtain a copy
- * of the License at http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software distributed under
- * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
- * OF ANY KIND, either express or implied. See the License for the specific language
- * governing permissions and limitations under the License.
- */
-
-
-
-
-
-
-
-
-
-export {$18f2051aff69b9bf$export$a54013f0d02a8f82 as I18nProvider, $18f2051aff69b9bf$export$43bb16f9c6d9e3f7 as useLocale, $321bc95feeb923dd$export$ec23bf898b1eed85 as useMessageFormatter, $fca6afa0e843324b$export$f12b703ca79dfbb1 as useLocalizedStringFormatter, $fca6afa0e843324b$export$87b761675e8eaa10 as useLocalizedStringDictionary, $33bf17300c498528$export$a2f47a3d2973640 as useListFormatter, $896ba0a80a8f4d36$export$85fd5fdf27bacc79 as useDateFormatter, $a916eb452884faea$export$b7a616150fdb9f44 as useNumberFormatter, $325a3faab7a68acd$export$a16aca283550c30d as useCollator, $bb77f239b46e8c72$export$3274cf84b703fff as useFilter};
-//# sourceMappingURL=module.js.map
+// Slim barrel: removed useDateFormatter (@internationalized/date ~40KB) and useMessageFormatter (@formatjs ~62KB)
+export {$18f2051aff69b9bf$export$a54013f0d02a8f82 as I18nProvider, $18f2051aff69b9bf$export$43bb16f9c6d9e3f7 as useLocale, $fca6afa0e843324b$export$f12b703ca79dfbb1 as useLocalizedStringFormatter, $fca6afa0e843324b$export$87b761675e8eaa10 as useLocalizedStringDictionary, $a916eb452884faea$export$b7a616150fdb9f44 as useNumberFormatter, $325a3faab7a68acd$export$a16aca283550c30d as useCollator, $bb77f239b46e8c72$export$3274cf84b703fff as useFilter};

View File

@@ -0,0 +1,24 @@
diff --git a/lib/index.js b/lib/index.js
index b7ea5e30fddb9bdef0034c00f28bbd4f0dee584a..47f7717632bd55d3c42ebb39f1ef5a23c14cfa3a 100644
--- a/lib/index.js
+++ b/lib/index.js
@@ -2,8 +2,8 @@ import { upperFirst, capitalize, parseFloat as parseFloat$1, without, pick, comp
import * as P from '@react-pdf/primitives';
import resolveStyle, { transformColor, flatten } from '@react-pdf/stylesheet';
import layoutEngine, { fontSubstitution, wordHyphenation, scriptItemizer, textDecoration, justification, linebreaker, bidi, fromFragments } from '@react-pdf/textkit';
-import * as Yoga from 'yoga-layout/load';
-import { loadYoga as loadYoga$1 } from 'yoga-layout/load';
+import * as Yoga from 'yoga-layout/dist/src/load.js';
+import { loadYoga as loadYoga$1 } from 'yoga-layout/dist/src/load.js';
import emojiRegex from 'emoji-regex-xs';
import resolveImage from '@react-pdf/image';
@@ -2998,7 +2998,7 @@ const splitPage = (page, pageNumber, fontStore, yoga) => {
const dynamicPage = resolveDynamicPage({ pageNumber }, page, fontStore, yoga);
const height = page.style.height;
const [currentChilds, nextChilds] = splitNodes(wrapArea, contentArea, dynamicPage.children);
- const relayout = (node) =>
+ const relayout = (node) =>
// @ts-expect-error rework pagination
relayoutPage(node, fontStore, yoga);
const currentBox = { ...page.box, height };

Some files were not shown because too many files have changed in this diff Show More