Conversation
ericallam
commented
Feb 18, 2026
- Add .server-changes/ convention for tracking server-only changes
- Create scripts/enhance-release-pr.mjs to deduplicate and categorize changeset PR body
- Create scripts/generate-github-release.mjs to format unified GitHub release body
- Change release.yml to create one unified GitHub release instead of per-package releases
- Add update-release job to patch Docker image link after images are pushed to GHCR
- Update changesets-pr.yml to trigger on .server-changes, enhance PR body, and clean up consumed files
- Document server changes in CLAUDE.md, CONTRIBUTING.md, CHANGESETS.md, and RELEASE.md
…lease PR - Add .server-changes/ convention for tracking server-only changes - Create scripts/enhance-release-pr.mjs to deduplicate and categorize changeset PR body - Create scripts/generate-github-release.mjs to format unified GitHub release body - Change release.yml to create one unified GitHub release instead of per-package releases - Add update-release job to patch Docker image link after images are pushed to GHCR - Update changesets-pr.yml to trigger on .server-changes, enhance PR body, and clean up consumed files - Document server changes in CLAUDE.md, CONTRIBUTING.md, CHANGESETS.md, and RELEASE.md
|
WalkthroughAdds a server-only changes convention with a new .server-changes/ README and updates docs (CHANGESETS.md, RELEASE.md, CONTRIBUTING.md, CLAUDE.md) to describe its usage. Updates CI workflows (.github/workflows/changesets-pr.yml and release.yml) to trigger on .server-changes/**, enhance PR titles and bodies (via a Node script), clean up non-README .server-changes files before lockfile commits, create a unified GitHub release, and update release bodies with tag-specific Docker links. Introduces two Node.js scripts: scripts/enhance-release-pr.mjs (composes enhanced PR bodies including .server-changes entries) and scripts/generate-github-release.mjs (formats GitHub release notes). Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes 🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (6)
.server-changes/README.md (1)
17-19: Missing language on fenced code block (markdownlint MD040).🔧 Proposed fix
-``` +```text .server-changes/fix-batch-queue-stalls.md</details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against the current code and only fix it if needed.
In @.server-changes/README.md around lines 17 - 19, The README's fenced code
block showing ".server-changes/fix-batch-queue-stalls.md" is missing a language
specifier (markdownlint MD040); update the fenced block in
.server-changes/README.md to include a language token (e.g., add "text" after
the opening), so the block becomestext ... ```, ensuring the code fence
around ".server-changes/fix-batch-queue-stalls.md" is annotated.</details> </blockquote></details> <details> <summary>.github/workflows/changesets-pr.yml (1)</summary><blockquote> `66-73`: **Redundant stdin pipe; `CHANGESET_PR_BODY` always takes precedence.** In `enhance-release-pr.mjs` (line 231), `process.env.CHANGESET_PR_BODY` is checked first and stdin is only read when that env var is falsy. Since `CHANGESET_PR_BODY="$RAW_BODY"` is always set here, the `echo "$RAW_BODY" |` pipe is dead code. Remove it to clarify intent. <details> <summary>🔧 Proposed fix</summary> ```diff - ENHANCED_BODY=$(echo "$RAW_BODY" | CHANGESET_PR_BODY="$RAW_BODY" node scripts/enhance-release-pr.mjs "$VERSION") + ENHANCED_BODY=$(CHANGESET_PR_BODY="$RAW_BODY" node scripts/enhance-release-pr.mjs "$VERSION") ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against the current code and only fix it if needed. In @.github/workflows/changesets-pr.yml around lines 66 - 73, The pipe `echo "$RAW_BODY" |` is redundant because enhance-release-pr.mjs checks process.env.CHANGESET_PR_BODY first; set the env var directly and remove the stdin pipe: export/pass CHANGESET_PR_BODY="$RAW_BODY" when invoking node and call node scripts/enhance-release-pr.mjs "$VERSION" (so CHANGESET_PR_BODY is available to the script), and delete the unused echo/stdin pipeline; update the block that defines RAW_BODY/ENHANCED_BODY to only set ENHANCED_BODY=$(CHANGESET_PR_BODY="$RAW_BODY" node scripts/enhance-release-pr.mjs "$VERSION") or equivalent and remove the dead pipe. ``` </details> </blockquote></details> <details> <summary>CHANGESETS.md (1)</summary><blockquote> `1-46`: **LGTM.** The expanded guidance is clear and consistent with the rest of the PR. One minor item flagged by `markdownlint` (MD059): the link text `"here"` on line 7 is non-descriptive. Consider replacing it with something like `"the changesets adding-a-changeset guide"`. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against the current code and only fix it if needed. In `@CHANGESETS.md` around lines 1 - 46, Replace the non-descriptive link text "here" in the "To add a changeset (package changes)" paragraph with a descriptive label such as "the changesets adding-a-changeset guide" (i.e., update the markdown link text that currently reads `[here](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md)`), so the link is self-descriptive and satisfies MD059. ``` </details> </blockquote></details> <details> <summary>scripts/generate-github-release.mjs (3)</summary><blockquote> `88-101`: **Contributor with a real name but a `noreply.github.com` email is silently dropped if the regex doesn't match.** On line 91, if `email?.includes("noreply.github.com")` is true but the regex on line 93 fails (e.g., the email format is `user@github.noreply.github.com` — an unexpected subdomain), the contributor is skipped entirely via `continue`. The `name` is available and valid in that case but never recorded. CodeQL also flags the substring check as an incomplete match. Consider falling back to `name` when the noreply regex doesn't match: <details> <summary>Proposed fix</summary> ```diff for (const line of log.split("\n").filter(Boolean)) { const [name, email] = line.split("|"); - if (!name || email?.includes("noreply.github.com")) { - // Try to extract username from noreply email - const match = email?.match(/(\d+\+)?(.+)@users\.noreply\.github\.com/); + if (email?.endsWith("@users.noreply.github.com")) { + const match = email.match(/(\d+\+)?(.+)@users\.noreply\.github\.com/); if (match) { const username = match[2]; contributors.set(username, (contributors.get(username) || 0) + 1); - } - continue; + } else if (name) { + contributors.set(name, (contributors.get(name) || 0) + 1); + } + continue; } + if (!name) continue; contributors.set(name, (contributors.get(name) || 0) + 1); } ``` </details> Using `endsWith` instead of `includes` also addresses the CodeQL substring sanitization warning. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against the current code and only fix it if needed. In `@scripts/generate-github-release.mjs` around lines 88 - 101, The contributors aggregation currently skips entries when email.includes("noreply.github.com") is true but the regex on email.match(...) fails; update the loop that builds the contributors Map so it uses email?.endsWith("noreply.github.com") instead of includes(), and if the noreply regex does not match, fall back to using the provided name (i.e., call contributors.set(name, ...) rather than continue). Keep the existing logic that increments counts when a username is extracted from the regex (contributors.set(username, ...)) and only fall back to name when regex returns null. ``` </details> --- `113-131`: **Prefer `readFileSync` over shelling out to `cat`.** `execSync("cat .changeset/config.json", …)` spawns an unnecessary shell process. `readFileSync` is simpler, faster, and portable. <details> <summary>Proposed change</summary> ```diff +import { readFileSync } from "fs"; + function getPublishedPackages() { try { - const config = JSON.parse( - execSync("cat .changeset/config.json", { - cwd: ROOT_DIR, - encoding: "utf-8", - }) - ); + const config = JSON.parse( + readFileSync(join(ROOT_DIR, ".changeset", "config.json"), "utf-8") + ); const fixed = config.fixed?.[0] || []; return fixed; } catch { ``` </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against the current code and only fix it if needed. In `@scripts/generate-github-release.mjs` around lines 113 - 131, The function getPublishedPackages currently shells out with execSync("cat .changeset/config.json", ...) which is inefficient; replace that call by reading the file directly using fs.readFileSync(path, "utf-8") (require/import fs at top if needed), then JSON.parse the returned string to populate config and derive fixed as config.fixed?.[0] || []; keep the same try/catch behavior and the same fallback array when reading/parsing fails so behavior of getPublishedPackages remains unchanged. ``` </details> --- `78-101`: **Unsanitized `version` interpolated into `execSync` shell string — potential command injection.** `version` comes directly from `process.argv[2]` and is interpolated into the shell command on line 83. While this is a CI script with presumably controlled inputs, a malformed version like `1.0.0; rm -rf /` would be executed by the shell. Prefer `execFileSync` (which bypasses the shell) or at minimum validate the version format at the top of the script. <details> <summary>Option A: validate version format early (minimal change)</summary> ```diff const version = process.argv[2]; if (!version) { console.error("Usage: node scripts/generate-github-release.mjs <version>"); process.exit(1); } +if (!/^\d+\.\d+\.\d+(-[\w.]+)?$/.test(version)) { + console.error(`Invalid version format: ${version}`); + process.exit(1); +} ``` </details> <details> <summary>Option B: use execFileSync to avoid shell interpolation</summary> ```diff - const log = execSync(`git log ${range} --format="%aN|%aE" --no-merges`, { + const log = execFileSync("git", ["log", range, "--format=%aN|%aE", "--no-merges"], { cwd: ROOT_DIR, encoding: "utf-8", }); ``` (Remember to import `execFileSync` from `child_process`.) </details> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against the current code and only fix it if needed. In `@scripts/generate-github-release.mjs` around lines 78 - 101, The git range string in getContributors interpolates previousVersion into an execSync shell command (execSync(`git log ${range} ...`)), which allows command injection via a malicious version; fix by either validating previousVersion early (ensure it matches a strict semver or /^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?$/) before using it, or switch to a shell-avoiding call: replace the execSync usage with execFileSync/child_process.spawnSync passing ['log', range, '--format=...','--no-merges'] (or split the range into a single safe arg) so no shell interpolation occurs; update imports to include execFileSync/child_process as needed and keep the rest of getContributors logic intact. ``` </details> </blockquote></details> </blockquote></details> <details> <summary>📜 Review details</summary> **Configuration used**: Repository UI **Review profile**: CHILL **Plan**: Pro <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between eb0f96339378ed6e08810a6ca442f3e5af47830f and 579248d929c022a54ab41a95a24b182a35683e3a. </details> <details> <summary>📒 Files selected for processing (10)</summary> * `.github/workflows/changesets-pr.yml` * `.github/workflows/release.yml` * `.server-changes/.gitkeep` * `.server-changes/README.md` * `CHANGESETS.md` * `CLAUDE.md` * `CONTRIBUTING.md` * `RELEASE.md` * `scripts/enhance-release-pr.mjs` * `scripts/generate-github-release.mjs` </details> <details> <summary>🧰 Additional context used</summary> <details> <summary>📓 Path-based instructions (1)</summary> <details> <summary>**/*.{js,ts,jsx,tsx,json,md,yaml,yml}</summary> **📄 CodeRabbit inference engine (AGENTS.md)** > Format code using Prettier before committing Files: - `CONTRIBUTING.md` - `RELEASE.md` - `CHANGESETS.md` - `CLAUDE.md` </details> </details><details> <summary>🧠 Learnings (5)</summary> <details> <summary>📓 Common learnings</summary> ``` Learnt from: CR Repo: triggerdotdev/trigger.dev PR: 0 File: CLAUDE.md:0-0 Timestamp: 2026-01-15T11:50:06.067Z Learning: Applies to {packages,integrations}/**/* : Add a changeset when modifying any public package in `packages/*` or `integrations/*` using `pnpm run changeset:add` ``` </details> <details> <summary>📚 Learning: 2026-01-15T11:50:06.067Z</summary> ``` Learnt from: CR Repo: triggerdotdev/trigger.dev PR: 0 File: CLAUDE.md:0-0 Timestamp: 2026-01-15T11:50:06.067Z Learning: Applies to {packages,integrations}/**/* : Add a changeset when modifying any public package in `packages/*` or `integrations/*` using `pnpm run changeset:add` ``` **Applied to files:** - `CONTRIBUTING.md` - `RELEASE.md` - `.github/workflows/changesets-pr.yml` - `CHANGESETS.md` - `CLAUDE.md` - `.server-changes/README.md` </details> <details> <summary>📚 Learning: 2026-01-15T11:50:06.067Z</summary> ``` Learnt from: CR Repo: triggerdotdev/trigger.dev PR: 0 File: CLAUDE.md:0-0 Timestamp: 2026-01-15T11:50:06.067Z Learning: Default to patch version for changesets for bug fixes and minor changes; confirm with maintainers before selecting minor or major ``` **Applied to files:** - `CLAUDE.md` </details> <details> <summary>📚 Learning: 2025-11-27T16:26:58.661Z</summary> ``` Learnt from: CR Repo: triggerdotdev/trigger.dev PR: 0 File: .cursor/rules/webapp.mdc:0-0 Timestamp: 2025-11-27T16:26:58.661Z Learning: Applies to apps/webapp/app/services/**/*.server.{ts,tsx} : Separate testable services from configuration files; follow the pattern of `realtimeClient.server.ts` (testable service) and `realtimeClientGlobal.server.ts` (configuration) in the webapp ``` **Applied to files:** - `.server-changes/README.md` </details> <details> <summary>📚 Learning: 2025-11-26T14:40:07.146Z</summary> ``` Learnt from: ericallam Repo: triggerdotdev/trigger.dev PR: 2710 File: packages/schema-to-json/package.json:0-0 Timestamp: 2025-11-26T14:40:07.146Z Learning: Node.js 24+ has native TypeScript support and can execute .ts files directly without tsx or ts-node for scripts that use only erasable TypeScript syntax (type annotations, interfaces, etc.). The trigger.dev repository uses Node.js 24.11.1+ and scripts like updateVersion.ts can be run with `node` instead of `tsx`. ``` **Applied to files:** - `scripts/generate-github-release.mjs` </details> </details><details> <summary>🧬 Code graph analysis (2)</summary> <details> <summary>scripts/enhance-release-pr.mjs (1)</summary><blockquote> <details> <summary>scripts/generate-github-release.mjs (4)</summary> * `version` (22-22) * `ROOT_DIR` (28-28) * `lines` (43-43) * `lines` (147-147) </details> </blockquote></details> <details> <summary>scripts/generate-github-release.mjs (1)</summary><blockquote> <details> <summary>scripts/enhance-release-pr.mjs (7)</summary> * `version` (23-23) * `ROOT_DIR` (29-29) * `body` (241-246) * `lines` (127-127) * `match` (110-110) * `parts` (151-151) * `chunks` (233-233) </details> </blockquote></details> </details><details> <summary>🪛 GitHub Check: CodeQL</summary> <details> <summary>scripts/generate-github-release.mjs</summary> [failure] 91-91: Incomplete URL substring sanitization '[noreply.github.com](1)' can be anywhere in the URL, and arbitrary hosts may come before or after it. </details> </details> <details> <summary>🪛 LanguageTool</summary> <details> <summary>RELEASE.md</summary> [uncategorized] ~8-~8: The official name of this software platform is spelled with a capital “H”. Context: ...only changes). 2. The [changesets-pr.yml](./.github/workflows/changesets-pr.yml) workflow a... (GITHUB) --- [uncategorized] ~10-~10: The official name of this software platform is spelled with a capital “H”. Context: ...ease PR into `main`. 4. The [release.yml](./.github/workflows/release.yml) workflow automat... (GITHUB) </details> <details> <summary>CHANGESETS.md</summary> [uncategorized] ~43-~43: The official name of this software platform is spelled with a capital “H”. Context: ...he `main` branch, the [changesets-pr.yml](./.github/workflows/changesets-pr.yml) workflow w... (GITHUB) --- [uncategorized] ~46-~46: The official name of this software platform is spelled with a capital “H”. Context: ... is merged into `main`, the [release.yml](./.github/workflows/release.yml) workflow will au... (GITHUB) </details> <details> <summary>.server-changes/README.md</summary> [grammar] ~3-~3: Ensure spelling is correct Context: ...acks changes to server-only components (webapp, supervisor, coordinator, etc.) that ar... (QB_NEW_EN_ORTHOGRAPHY_ERROR_IDS_1) </details> </details> <details> <summary>🪛 markdownlint-cli2 (0.21.0)</summary> <details> <summary>CHANGESETS.md</summary> [warning] 7-7: Link text should be descriptive (MD059, descriptive-link-text) </details> <details> <summary>CLAUDE.md</summary> [warning] 85-85: Fenced code blocks should have a language specified (MD040, fenced-code-language) --- [warning] 94-94: Fenced code blocks should have a language specified (MD040, fenced-code-language) </details> <details> <summary>.server-changes/README.md</summary> [warning] 17-17: Fenced code blocks should have a language specified (MD040, fenced-code-language) </details> </details> </details> <details> <summary>⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (26)</summary> * GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8) * GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8) * GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8) * GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8) * GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8) * GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8) * GitHub Check: sdk-compat / Cloudflare Workers * GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8) * GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8) * GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8) * GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8) * GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8) * GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8) * GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8) * GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8) * GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8) * GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8) * GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1) * GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm) * GitHub Check: typecheck / typecheck * GitHub Check: sdk-compat / Deno Runtime * GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm) * GitHub Check: sdk-compat / Bun Runtime * GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm) * GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest) * GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest) </details> <details> <summary>🔇 Additional comments (5)</summary><blockquote> <details> <summary>CONTRIBUTING.md (1)</summary><blockquote> `270-301`: **LGTM.** New section is clear and consistent with CHANGESETS.md and CLAUDE.md. </blockquote></details> <details> <summary>RELEASE.md (1)</summary><blockquote> `3-22`: **LGTM.** Automated release documentation clearly describes the v4+ flow and engineer responsibilities. </blockquote></details> <details> <summary>CLAUDE.md (1)</summary><blockquote> `70-99`: **LGTM.** Guidance is consistent with CHANGESETS.md and CONTRIBUTING.md. The `markdownlint` MD040 warnings on lines 85 and 94 are false positives — the linter is misinterpreting `---` YAML frontmatter delimiters inside the heredoc as fenced code block markers. </blockquote></details> <details> <summary>scripts/generate-github-release.mjs (2)</summary><blockquote> `40-74`: **`extractChangesFromPrBody`: once `<details>` is entered, `inDetails` is never reset — all subsequent content is dropped.** This appears intentional (the `<details>` block and everything after it is raw changeset output that should be stripped). Just confirming: if the enhanced PR body ever contains a `<details>` block *within* the curated sections (e.g., collapsible sub-sections), that content and everything below will be silently lost. If that's the expected format, this is fine. Otherwise, pair the flag with `</details>` tracking. --- `210-231`: **Main orchestration looks correct.** The stdin fallback, extraction, and formatting flow are well-structured. One minor observation: `getPreviousVersion(version)` is computed both here (line 220) and inside `formatRelease` (line 198). You could compute it once and pass it through, but it's a pure function so this is harmless. </blockquote></details> </blockquote></details> </details> <details> <summary>🤖 Prompt for all review comments with AI agents</summary>Verify each finding against the current code and only fix it if needed.
Inline comments:
In @.github/workflows/changesets-pr.yml:
- Around line 101-110: The cleanup loop using set -e iterates
files=(.server-changes/*.md) and runs git rm "$f" which will cause the step to
fail if a file is untracked; update the git rm invocation in that for loop to
use git rm --ignore-unmatch "$f" so removals of untracked paths don't return
non-zero and the step remains idempotent (refer to the files array, the for f in
"${files[@]}" loop, and the git rm command).In @.github/workflows/release.yml:
- Around line 176-192: The VERSION_ID capture and URL replacement are fragile:
ensure VERSION_ID yields a single id by piping the gh/jq output through head -1
(or use jq limit) so VERSION_ID is never multiline; then make the replacement
idempotent by only substituting GENERIC_URL occurrences that are not already
part of DOCKER_URL (e.g., check CURRENT_BODY for the presence of DOCKER_URL and
skip replacement if found, or replace only exact matches of GENERIC_URL rather
than substrings inside existing DOCKER_URL) so UPDATED_BODY cannot double-expand
the URL; update the logic around VERSION_ID, DOCKER_URL, GENERIC_URL,
CURRENT_BODY and UPDATED_BODY accordingly.- Around line 125-136: The RELEASE_PR_BODY env var is empty on workflow_dispatch
because github.event.pull_request is undefined; update the job to detect an
empty RELEASE_PR_BODY and, before calling node
scripts/generate-github-release.mjs, populate it by querying the most-recently
merged release PR body (e.g., use gh api or gh pr list/gh pr view filtered by
label/title and state=merged to fetch the body) and export that as
RELEASE_PR_BODY so generate-github-release.mjs always receives a non-empty body;
keep existing use of RELEASE_PR_BODY and the node script but add the fallback
lookup step and assignment when github.event.pull_request.body is missing.In
@scripts/enhance-release-pr.mjs:
- Around line 92-96: The fs.readFile call inside the files loop can throw and
crash the script; wrap the await fs.readFile(join(dir, file), "utf-8") in a
try/catch inside the loop (the block that iterates over files in
scripts/enhance-release-pr.mjs) so that on error you log a warning (console.warn
or the existing logger) saying which file failed and why, then continue to the
next file instead of letting the exception propagate to the top; ensure you only
call parseFrontmatter(content) when the read succeeded.In
@scripts/generate-github-release.mjs:
- Around line 133-142: getPreviousVersion currently returns the same version for
major releases like "4.0.0" because neither the minor nor patch branches run;
update getPreviousVersion to detect the major-release case (when parts[1] === 0
&& parts[2] === 0) and handle it by decrementing the major (parts[0]--) and
setting parts[1] and parts[2] to large sentinel values (e.g., 999) so the
previous-version string is strictly less than the current one; this change in
getPreviousVersion will ensure getContributors' git log range and the "Full
changelog" comparison link are not empty/self-referencing.
Nitpick comments:
In @.github/workflows/changesets-pr.yml:
- Around line 66-73: The pipe
echo "$RAW_BODY" |is redundant because
enhance-release-pr.mjs checks process.env.CHANGESET_PR_BODY first; set the env
var directly and remove the stdin pipe: export/pass
CHANGESET_PR_BODY="$RAW_BODY" when invoking node and call node
scripts/enhance-release-pr.mjs "$VERSION" (so CHANGESET_PR_BODY is available to
the script), and delete the unused echo/stdin pipeline; update the block that
defines RAW_BODY/ENHANCED_BODY to only set
ENHANCED_BODY=$(CHANGESET_PR_BODY="$RAW_BODY" node
scripts/enhance-release-pr.mjs "$VERSION") or equivalent and remove the dead
pipe.In @.server-changes/README.md:
- Around line 17-19: The README's fenced code block showing
".server-changes/fix-batch-queue-stalls.md" is missing a language specifier
(markdownlint MD040); update the fenced block in .server-changes/README.md to
include a language token (e.g., add "text" after the opening), so the block becomestext ... ```, ensuring the code fence around
".server-changes/fix-batch-queue-stalls.md" is annotated.In
@CHANGESETS.md:
- Around line 1-46: Replace the non-descriptive link text "here" in the "To add
a changeset (package changes)" paragraph with a descriptive label such as "the
changesets adding-a-changeset guide" (i.e., update the markdown link text that
currently reads
[here](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md)),
so the link is self-descriptive and satisfies MD059.In
@scripts/generate-github-release.mjs:
- Around line 88-101: The contributors aggregation currently skips entries when
email.includes("noreply.github.com") is true but the regex on email.match(...)
fails; update the loop that builds the contributors Map so it uses
email?.endsWith("noreply.github.com") instead of includes(), and if the noreply
regex does not match, fall back to using the provided name (i.e., call
contributors.set(name, ...) rather than continue). Keep the existing logic that
increments counts when a username is extracted from the regex
(contributors.set(username, ...)) and only fall back to name when regex returns
null.- Around line 113-131: The function getPublishedPackages currently shells out
with execSync("cat .changeset/config.json", ...) which is inefficient; replace
that call by reading the file directly using fs.readFileSync(path, "utf-8")
(require/import fs at top if needed), then JSON.parse the returned string to
populate config and derive fixed as config.fixed?.[0] || []; keep the same
try/catch behavior and the same fallback array when reading/parsing fails so
behavior of getPublishedPackages remains unchanged.- Around line 78-101: The git range string in getContributors interpolates
previousVersion into an execSync shell command (execSync(git log ${range} ...)), which allows command injection via a malicious version; fix by either
validating previousVersion early (ensure it matches a strict semver or
/^[0-9]+.[0-9]+.[0-9]+(-[0-9A-Za-z.-]+)?$/) before using it, or switch to a
shell-avoiding call: replace the execSync usage with
execFileSync/child_process.spawnSync passing ['log', range,
'--format=...','--no-merges'] (or split the range into a single safe arg) so no
shell interpolation occurs; update imports to include execFileSync/child_process
as needed and keep the rest of getContributors logic intact.</details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
scripts/generate-github-release.mjs (1)
224-228:getPreviousVersion(version)is computed twice — minor redundancy.It is called in
main()(Line 246, as the argument togetContributors) and again insideformatRelease()(Line 224). Consider computing it once inmain()and passing it intoformatRelease.♻️ Proposed refactor
-function formatRelease({ version, changesContent, contributors, packages }) { +function formatRelease({ version, changesContent, contributors, packages, prevVersion }) { const lines = []; // ... // Comparison link - const prevVersion = getPreviousVersion(version); if (prevVersion) {+ const prevVersion = getPreviousVersion(version); const changesContent = extractChangesFromPrBody(prBody); - const contributors = getContributors(getPreviousVersion(version)); + const contributors = getContributors(prevVersion); const packages = getPublishedPackages(); const body = formatRelease({ version, changesContent, contributors, packages, + prevVersion, });🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/generate-github-release.mjs` around lines 224 - 228, Compute getPreviousVersion(version) once in main(), store it (e.g., prevVersion) and pass that value into formatRelease(prevVersion, version, ...) instead of calling getPreviousVersion inside formatRelease; also update the getContributors call in main() to use the same prevVersion variable so both getContributors(...) and formatRelease(...) consume the single precomputed prevVersion, and remove the redundant getPreviousVersion call from inside formatRelease.
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
.github/workflows/changesets-pr.yml.github/workflows/release.ymlscripts/generate-github-release.mjs
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to {packages,integrations}/**/* : Add a changeset when modifying any public package in `packages/*` or `integrations/*` using `pnpm run changeset:add`
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to {packages,integrations}/**/* : Add a changeset when modifying any public package in `packages/*` or `integrations/*` using `pnpm run changeset:add`
Applied to files:
.github/workflows/changesets-pr.ymlscripts/generate-github-release.mjs
📚 Learning: 2025-09-03T14:35:52.384Z
Learnt from: myftija
Repo: triggerdotdev/trigger.dev PR: 2464
File: apps/webapp/app/utils/pathBuilder.ts:144-146
Timestamp: 2025-09-03T14:35:52.384Z
Learning: In the trigger.dev codebase, organization slugs are safe for URL query parameters and don't require URL encoding, as confirmed by the maintainer in apps/webapp/app/utils/pathBuilder.ts.
Applied to files:
scripts/generate-github-release.mjs
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Use build extensions in trigger.config.ts (additionalFiles, additionalPackages, aptGet, prismaExtension, etc.) to customize the build
Applied to files:
scripts/generate-github-release.mjs
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to packages/trigger-sdk/**/*.{ts,tsx} : In the Trigger.dev SDK (packages/trigger-sdk), prefer isomorphic code like fetch and ReadableStream instead of Node.js-specific code
Applied to files:
scripts/generate-github-release.mjs
🪛 GitHub Check: CodeQL
scripts/generate-github-release.mjs
[failure] 102-102: Incomplete URL substring sanitization
'noreply.github.com' may be preceded by an arbitrary host name.
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (28)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
- GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
- GitHub Check: sdk-compat / Deno Runtime
- GitHub Check: sdk-compat / Cloudflare Workers
- GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
- GitHub Check: sdk-compat / Bun Runtime
- GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
- GitHub Check: typecheck / typecheck
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
scripts/generate-github-release.mjs (1)
153-168:getPreviousVersionmajor-version case is now handled correctly — LGTM.The
parts[0] > 0branch (Line 160) resolves the previously flagged issue where4.0.0would return itself.4.0.0→3.0.0is the correct previous published major, and the resultingv3.0.0...HEADgit range is valid..github/workflows/changesets-pr.yml (2)
101-110:git rm --ignore-unmatchfix applied — LGTM.The cleanup loop is now idempotent:
--ignore-unmatchexits cleanly when a.server-changes/*.mdfile is not tracked by git, andshopt -s nullglobcorrectly prevents the loop from running when no files match.
112-123: Commit step correctly covers both lockfile and.server-changes/cleanup — LGTM.
git add pnpm-lock.yamlstages the lockfile, whilegit rm --ignore-unmatchfrom the previous step already staged the file deletions;git diff --cached --quiettherefore detects either type of change before committing..github/workflows/release.yml (2)
113-114:createGithubReleases: falsecorrectly defers to the unified custom release step — LGTM.
156-195:update-release: priorVERSION_IDand idempotency issues are now resolved — LGTM.
head -1(Line 179) guarantees a single ID even if thejqstream emits multiple matches.- The
sedpatterns|${GENERIC_URL})|${DOCKER_URL})|g(Line 193) matches only the bare closing)of the original placeholder link; the already-substituted URL ends with/VERSION_ID?tag=TAG)and will not re-match, making the step idempotent on retries.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@scripts/generate-github-release.mjs`:
- Around line 102-109: The endsWith check is too broad and the regex failure
causes contributors to be skipped; update the conditional to use
email?.endsWith("@users.noreply.github.com") (include the leading @) and, inside
the branch where you run const match =
email?.match(/(\d+\+)?(.+)@users\.noreply\.github\.com/), remove the
unconditional continue on regex failure so that when match is null you fall
through to the normal contributor-addition logic (using the existing name
variable or falling back to a sensible email-derived identifier) instead of
silently dropping the contributor; ensure you still increment contributors via
contributors.set(username, ...) when match succeeds.
---
Duplicate comments:
In @.github/workflows/release.yml:
- Around line 125-136: The workflow sets RELEASE_PR_BODY from
github.event.pull_request.body which is undefined for workflow_dispatch, causing
empty release notes; update the release job to detect when RELEASE_PR_BODY is
empty and fall back to retrieving the most recent merged release PR body (e.g.,
via gh pr list --state merged --head changeset-release/main --limit 1 --json
body) before running node scripts/generate-github-release.mjs, and pass that
fallback value into the RELEASE_PR_BODY env used by generate-github-release.mjs
so the script can include the "What's changed" section when no pull_request
payload exists.
---
Nitpick comments:
In `@scripts/generate-github-release.mjs`:
- Around line 224-228: Compute getPreviousVersion(version) once in main(), store
it (e.g., prevVersion) and pass that value into formatRelease(prevVersion,
version, ...) instead of calling getPreviousVersion inside formatRelease; also
update the getContributors call in main() to use the same prevVersion variable
so both getContributors(...) and formatRelease(...) consume the single
precomputed prevVersion, and remove the redundant getPreviousVersion call from
inside formatRelease.
scripts/generate-github-release.mjs
Outdated
There was a problem hiding this comment.
CodeQL: endsWith("noreply.github.com") is too broad — use "@users.noreply.github.com".
Any email ending with noreply.github.com matches the condition, including fabricated addresses like user@evil-noreply.github.com. When the regex /(\d+\+)?(.+)@users\.noreply\.github\.com/ fails to match such an address, the contributor is silently dropped from the list instead of being added by name.
🐛 Proposed fix
- if (!name || email?.endsWith("noreply.github.com")) {
+ if (!name || email?.endsWith("@users.noreply.github.com")) {📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (!name || email?.endsWith("noreply.github.com")) { | |
| // Try to extract username from noreply email | |
| const match = email?.match(/(\d+\+)?(.+)@users\.noreply\.github\.com/); | |
| if (match) { | |
| const username = match[2]; | |
| contributors.set(username, (contributors.get(username) || 0) + 1); | |
| } | |
| continue; | |
| if (!name || email?.endsWith("@users.noreply.github.com")) { | |
| // Try to extract username from noreply email | |
| const match = email?.match(/(\d+\+)?(.+)@users\.noreply\.github\.com/); | |
| if (match) { | |
| const username = match[2]; | |
| contributors.set(username, (contributors.get(username) || 0) + 1); | |
| } | |
| continue; |
🧰 Tools
🪛 GitHub Check: CodeQL
[failure] 102-102: Incomplete URL substring sanitization
'noreply.github.com' may be preceded by an arbitrary host name.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@scripts/generate-github-release.mjs` around lines 102 - 109, The endsWith
check is too broad and the regex failure causes contributors to be skipped;
update the conditional to use email?.endsWith("@users.noreply.github.com")
(include the leading @) and, inside the branch where you run const match =
email?.match(/(\d+\+)?(.+)@users\.noreply\.github\.com/), remove the
unconditional continue on regex failure so that when match is null you fall
through to the normal contributor-addition logic (using the existing name
variable or falling back to a sensible email-derived identifier) instead of
silently dropping the contributor; ensure you still increment contributors via
contributors.set(username, ...) when match succeeds.
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
scripts/generate-github-release.mjs (1)
236-254:getPreviousVersion(version)is computed twice — consider computing it once inmain.
getPreviousVersionis a pure function but is called at Line 246 (to pass togetContributors) and again at Line 224 insideformatRelease. Unifying the call site makes the dependency explicit and removes the implicit coupling.♻️ Proposed refactor
async function main() { // ... + const prevVersion = getPreviousVersion(version); - const contributors = getContributors(getPreviousVersion(version)); + const contributors = getContributors(prevVersion); const packages = getPublishedPackages(); const body = formatRelease({ version, + prevVersion, changesContent, contributors, packages, }); // ... }-function formatRelease({ version, changesContent, contributors, packages }) { +function formatRelease({ version, prevVersion, changesContent, contributors, packages }) { // ... - const prevVersion = getPreviousVersion(version); if (prevVersion) {🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/generate-github-release.mjs` around lines 236 - 254, Compute getPreviousVersion once in main and pass that value down instead of calling getPreviousVersion(version) multiple times: in main, create a const previousVersion = getPreviousVersion(version); then call getContributors(previousVersion) and call formatRelease({version, previousVersion, changesContent, contributors, packages}); update formatRelease's signature (and any call sites) to accept previousVersion and remove its internal call to getPreviousVersion so the dependency is explicit and the duplicate computation is eliminated.
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
scripts/generate-github-release.mjs
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to {packages,integrations}/**/* : Add a changeset when modifying any public package in `packages/*` or `integrations/*` using `pnpm run changeset:add`
📚 Learning: 2025-11-26T14:40:07.146Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 2710
File: packages/schema-to-json/package.json:0-0
Timestamp: 2025-11-26T14:40:07.146Z
Learning: Node.js 24+ has native TypeScript support and can execute .ts files directly without tsx or ts-node for scripts that use only erasable TypeScript syntax (type annotations, interfaces, etc.). The trigger.dev repository uses Node.js 24.11.1+ and scripts like updateVersion.ts can be run with `node` instead of `tsx`.
Applied to files:
scripts/generate-github-release.mjs
📚 Learning: 2025-09-03T14:35:52.384Z
Learnt from: myftija
Repo: triggerdotdev/trigger.dev PR: 2464
File: apps/webapp/app/utils/pathBuilder.ts:144-146
Timestamp: 2025-09-03T14:35:52.384Z
Learning: In the trigger.dev codebase, organization slugs are safe for URL query parameters and don't require URL encoding, as confirmed by the maintainer in apps/webapp/app/utils/pathBuilder.ts.
Applied to files:
scripts/generate-github-release.mjs
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Use build extensions in trigger.config.ts (additionalFiles, additionalPackages, aptGet, prismaExtension, etc.) to customize the build
Applied to files:
scripts/generate-github-release.mjs
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to {packages,integrations}/**/* : Add a changeset when modifying any public package in `packages/*` or `integrations/*` using `pnpm run changeset:add`
Applied to files:
scripts/generate-github-release.mjs
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to packages/trigger-sdk/**/*.{ts,tsx} : In the Trigger.dev SDK (packages/trigger-sdk), prefer isomorphic code like fetch and ReadableStream instead of Node.js-specific code
Applied to files:
scripts/generate-github-release.mjs
🧬 Code graph analysis (1)
scripts/generate-github-release.mjs (1)
scripts/enhance-release-pr.mjs (5)
version(23-23)ROOT_DIR(29-29)body(241-246)lines(127-127)dir(82-82)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: units / webapp / 📊 Merge Reports
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
- GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
🔇 Additional comments (1)
scripts/generate-github-release.mjs (1)
124-151: No actionable issues found. The repository does not have a top-levelintegrations/directory; all packages are underpackages/, which the function correctly scans. All 9 non-private packages are included.Likely an incorrect or invalid review comment.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@scripts/generate-github-release.mjs`:
- Around line 100-116: The contributor parsing loop stores git author names
(from %aN) into the contributors Map which later causes formatRelease to emit
invalid `@mentions` for real names; update the parsing logic in the loop that
iterates over log.split(...) so that when you extract [name, email] you prefer a
GitHub login (from the noreply email match group) otherwise record a display
name without the leading '@' (or normalize by testing name against a
GitHub-handle pattern like /^[A-Za-z0-9-]+$/); ensure formatRelease uses the
stored value directly (no blind '@' prefix) so valid user logins are emitted as
`@username` and real names are emitted as plain text.
---
Duplicate comments:
In `@scripts/generate-github-release.mjs`:
- Around line 153-168: getPreviousVersion currently failed on major-version
rollbacks; update the function getPreviousVersion to decrement the major part
(parts[0]) and reset minor and patch to 0 when receiving X.0.0 (i.e., if
parts[0] > 0 then parts[0]--, parts[1]=0, parts[2]=0) and return null only for
0.0.0; ensure this logic is implemented in the getPreviousVersion function so
git log ranges and changelog links do not self-reference.
- Around line 102-110: The previous broad endsWith check has been corrected to
the anchored "@users.noreply.github.com"; leave the logic in the block using
email?.match(/(\d+\+)?(.+)@users\.noreply\.github\.com/) as-is, but ensure the
code continues to safely handle missing/undefined email and that match[2]
(username) is present before calling contributors.set(username, ...); no further
change required other than keeping the anchored string and the null-safe checks
around email and match.
---
Nitpick comments:
In `@scripts/generate-github-release.mjs`:
- Around line 236-254: Compute getPreviousVersion once in main and pass that
value down instead of calling getPreviousVersion(version) multiple times: in
main, create a const previousVersion = getPreviousVersion(version); then call
getContributors(previousVersion) and call formatRelease({version,
previousVersion, changesContent, contributors, packages}); update
formatRelease's signature (and any call sites) to accept previousVersion and
remove its internal call to getPreviousVersion so the dependency is explicit and
the duplicate computation is eliminated.
There was a problem hiding this comment.
🧹 Nitpick comments (1)
scripts/generate-github-release.mjs (1)
228-228:getPreviousVersionis computed twice for the sameversion.It's called in
main(Line 250) to seedgetContributors, and again insideformatRelease(Line 228) for the comparison link. Computing it once and threading the result through would be a minimal cleaner.♻️ Suggested refactor
- const contributors = getContributors(getPreviousVersion(version)); + const prevVersion = getPreviousVersion(version); + const contributors = getContributors(prevVersion); const packages = getPublishedPackages(); const body = formatRelease({ version, changesContent, contributors, packages, + prevVersion, });Then update
formatReleaseto acceptprevVersiondirectly instead of recomputing it:-function formatRelease({ version, changesContent, contributors, packages }) { +function formatRelease({ version, changesContent, contributors, packages, prevVersion }) { // ... - const prevVersion = getPreviousVersion(version);Also applies to: 250-250
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@scripts/generate-github-release.mjs` at line 228, getPreviousVersion(version) is being called twice — once in main to seed getContributors and again inside formatRelease for the comparison link; compute it once and thread the result through. Change main to compute const prevVersion = getPreviousVersion(version) and pass that prevVersion into formatRelease (and any other callers like getContributors) so formatRelease(prevVersion, version, ...) uses the supplied value instead of calling getPreviousVersion internally; update the signature of formatRelease and any call sites accordingly (referencing getPreviousVersion, main, formatRelease, getContributors, version, prevVersion).
📜 Review details
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
scripts/generate-github-release.mjs
🧰 Additional context used
🧠 Learnings (6)
📓 Common learnings
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to {packages,integrations}/**/* : Add a changeset when modifying any public package in `packages/*` or `integrations/*` using `pnpm run changeset:add`
📚 Learning: 2025-11-26T14:40:07.146Z
Learnt from: ericallam
Repo: triggerdotdev/trigger.dev PR: 2710
File: packages/schema-to-json/package.json:0-0
Timestamp: 2025-11-26T14:40:07.146Z
Learning: Node.js 24+ has native TypeScript support and can execute .ts files directly without tsx or ts-node for scripts that use only erasable TypeScript syntax (type annotations, interfaces, etc.). The trigger.dev repository uses Node.js 24.11.1+ and scripts like updateVersion.ts can be run with `node` instead of `tsx`.
Applied to files:
scripts/generate-github-release.mjs
📚 Learning: 2025-09-03T14:35:52.384Z
Learnt from: myftija
Repo: triggerdotdev/trigger.dev PR: 2464
File: apps/webapp/app/utils/pathBuilder.ts:144-146
Timestamp: 2025-09-03T14:35:52.384Z
Learning: In the trigger.dev codebase, organization slugs are safe for URL query parameters and don't require URL encoding, as confirmed by the maintainer in apps/webapp/app/utils/pathBuilder.ts.
Applied to files:
scripts/generate-github-release.mjs
📚 Learning: 2025-11-27T16:27:35.304Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .cursor/rules/writing-tasks.mdc:0-0
Timestamp: 2025-11-27T16:27:35.304Z
Learning: Applies to **/trigger.config.ts : Use build extensions in trigger.config.ts (additionalFiles, additionalPackages, aptGet, prismaExtension, etc.) to customize the build
Applied to files:
scripts/generate-github-release.mjs
📚 Learning: 2026-01-15T11:50:06.067Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: CLAUDE.md:0-0
Timestamp: 2026-01-15T11:50:06.067Z
Learning: Applies to {packages,integrations}/**/* : Add a changeset when modifying any public package in `packages/*` or `integrations/*` using `pnpm run changeset:add`
Applied to files:
scripts/generate-github-release.mjs
📚 Learning: 2025-11-27T16:26:37.432Z
Learnt from: CR
Repo: triggerdotdev/trigger.dev PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2025-11-27T16:26:37.432Z
Learning: Applies to packages/trigger-sdk/**/*.{ts,tsx} : In the Trigger.dev SDK (packages/trigger-sdk), prefer isomorphic code like fetch and ReadableStream instead of Node.js-specific code
Applied to files:
scripts/generate-github-release.mjs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (28)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (8, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (1, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (3, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (6, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (7, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (4, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (5, 8)
- GitHub Check: units / webapp / 🧪 Unit Tests: Webapp (2, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (3, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (7, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (8, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (6, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (1, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (2, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (5, 8)
- GitHub Check: units / internal / 🧪 Unit Tests: Internal (4, 8)
- GitHub Check: units / packages / 🧪 Unit Tests: Packages (1, 1)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - pnpm)
- GitHub Check: sdk-compat / Cloudflare Workers
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - pnpm)
- GitHub Check: sdk-compat / Node.js 22.12 (ubuntu-latest)
- GitHub Check: e2e / 🧪 CLI v3 tests (ubuntu-latest - npm)
- GitHub Check: e2e / 🧪 CLI v3 tests (windows-latest - npm)
- GitHub Check: typecheck / typecheck
- GitHub Check: sdk-compat / Node.js 20.20 (ubuntu-latest)
- GitHub Check: sdk-compat / Bun Runtime
- GitHub Check: sdk-compat / Deno Runtime
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (5)
scripts/generate-github-release.mjs (5)
100-119: Both past issues with contributor extraction are resolved.The
endsWith("@users.noreply.github.com")guard (previously too broad, flagged by CodeQL) is now correct, and thecontinueat line 109 is safe because: when!nameis the trigger and the email doesn't match the noreply regex, there is nothing meaningful to store; when the noreply email is the trigger, the regex invariably matches. Good.
153-168:getPreviousVersionmajor-version case is now correctly handled.The
else if (parts[0] > 0)branch (Line 160) addresses the previously reported defect where4.0.0would return itself unchanged, resulting in an empty git-log range and a self-referencing changelog link. Theelse { return null; }guard for0.0.0is also a nice touch.
219-223: Contributor@-prefix handling correctly addresses the previous concern.The regex
/^[A-Za-z0-9][-A-Za-z0-9]*$/guards against prefixing@on real names with spaces (e.g.,"Jane Smith"is emitted as plain text, not@Jane Smith), fully resolving the prior comment about invalid GitHub mention strings.
124-151: Theintegrations/directory does not exist in the repository. The current implementation ofgetPublishedPackages()correctly scans only thepackages/directory where packages are actually stored. No fix is needed.Likely an incorrect or invalid review comment.
68-72: The concern about theinDetailsflag is not valid. Theenhance-release-pr.mjsscript only emits a single<details>block at the very end of the PR body (wrapping the raw changeset output), not within content sections. Content extraction will not be prematurely terminated.Likely an incorrect or invalid review comment.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@scripts/generate-github-release.mjs`:
- Line 228: getPreviousVersion(version) is being called twice — once in main to
seed getContributors and again inside formatRelease for the comparison link;
compute it once and thread the result through. Change main to compute const
prevVersion = getPreviousVersion(version) and pass that prevVersion into
formatRelease (and any other callers like getContributors) so
formatRelease(prevVersion, version, ...) uses the supplied value instead of
calling getPreviousVersion internally; update the signature of formatRelease and
any call sites accordingly (referencing getPreviousVersion, main, formatRelease,
getContributors, version, prevVersion).