Skip to content

Add CI checks for common workspace#12

Open
duck-master wants to merge 23 commits intosipec:mainfrom
duck-master:add-common-ci-checks
Open

Add CI checks for common workspace#12
duck-master wants to merge 23 commits intosipec:mainfrom
duck-master:add-common-ci-checks

Conversation

@duck-master
Copy link
Copy Markdown

@duck-master duck-master commented Aug 6, 2025

This is the second in my PR series (previously: this one). This was a lot more annoying (and also more sprawling!) than the first for several reasons:

  • I changed jest.config.js to use import style imports.
    • For some strange reason, if I did not add the with { type: "json" } statement when importing tsconfig.json directly, Jest would fail, but Prettier would succeed. However, if I did add this statement, Jest would succeed, but Prettier would fail. So neither worked. Instead, as a hacky workaround, I created a file called tsconfig.js which exports the exact same thing as tsconfig.json, and imported that instead. If there's a less hacky solution for this, I'd love to know.
  • ESLint marked the _apiTypeCheck variable as unused. I got around this by making it a type declaration.
  • There was one type error within the definition of typedAPICall in common/src/util/api.ts. Namely, one input, path, could conceivably be either a string or a number, but getApiUrl only expects a string input. I fixed this by stringifying it using the String() function. That said, this could conceivably lead to bugs if path does in fact happen to be a number and the app is expecting us to stringify it a different way.
  • For the implementation of binary search in common/src/util/algos.ts, there is a while true loop, which I fixed by limiting i to 1000002. However, you could write a cleaner version that explicitly frames the process as a for loop rather than a while loop. I considered this but decided against it since that would be a bigger change that would require me to write a new set of automated tests. (By the way, huge kudos for even setting up jest to begin with!)

Summary by CodeRabbit

  • New Features

    • Added automated CI for the common workspace: tests, linting, formatting checks, and type checks on relevant changes.
  • Refactor

    • Migrated test tooling config to ES module format.
    • Tightened binary search loop to enforce an iteration cap.
    • Simplified several imports and minor code cleanups.
  • Bug Fixes

    • Improved explicit typing and safer argument handling in API/util paths.
  • Chores

    • Added linting/type tooling dev-dependencies.
  • Documentation

    • Enhanced TypeScript config to support JSON imports and ESM interop.

@vercel
Copy link
Copy Markdown

vercel Bot commented Aug 6, 2025

@duck-master is attempting to deploy a commit to the polylove Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Aug 6, 2025

Walkthrough

Adds a CI workflow scoped to the common workspace, introduces ESLint config and dev dependencies, converts configs to ES modules (and adds a JS-exported tsconfig), and applies small refactors and formatting/consistency edits across multiple common source files (imports, type annotations, loop bounds, minor cleanups).

Changes

Cohort / File(s) Change Summary
CI Workflow
.github/workflows/ci-common.yml
New GitHub Actions workflow for common workspace with jobs: test, eslint, prettier, typecheck; triggers on PRs and pushes to main when common/** (excluding .md/.txt) change.
Linting & package metadata
common/eslint.config.mjs, common/package.json
Adds ESLint config and related devDependencies; disables two TS ESLint rules; sets package "type": "module".
Jest & TS config
common/jest.config.js, common/tsconfig.js, common/tsconfig.json
Jest config converted to ES module export; new common/tsconfig.js exports TS config object for runtime import; tsconfig.json adds resolveJsonModule and esModuleInterop.
API typing
common/src/api/schema.ts
Introduces apiTypeCheck type alias and explicitly types exported API constant with it (no shape changes).
Small refactors & cleanup
common/src/api/websocket-client.ts, common/src/api/zod-types.ts, common/src/envs/is-prod.ts, common/src/love/lover.ts, common/src/secrets.ts, common/src/util/api.ts, common/src/util/json.ts, common/src/util/parse.ts, common/src/util/random.ts, common/src/util/string.ts
Removes/comment-outs of unused imports, moves firebase-admin to static import, simplifies catch clauses (removes unused error vars), casts path to string in API helper, and ensures trailing newlines.
Tests formatting
common/src/socials.test.ts
Reformatting of expect calls into multi-line assertions; no logic changes.
Algorithm hard cap
common/src/util/algos.ts
Changes infinite while (true) in binarySearch to bounded while (i <= 100000) with existing iteration guard preserved.

Sequence Diagram(s)

sequenceDiagram
    participant GitHub
    participant CI_Workflow
    participant Runner
    participant Repo

    GitHub->>CI_Workflow: Trigger on PR/push (files: common/** excluding .md/.txt)
    CI_Workflow->>Runner: Start selected jobs (test, eslint, prettier, typecheck)
    Runner->>Repo: checkout
    Runner->>Runner: setup Node.js, install Yarn
    Runner->>Repo: install dependencies (yarn)
    alt test
        Runner->>Repo: run `yarn test`
    else eslint
        Runner->>Repo: run `yarn eslint .`
    else prettier
        Runner->>Repo: run `yarn prettier . --check --ignore-unknown`
    else typecheck
        Runner->>Repo: run `yarn tsc . --noEmit --strict`
    end
    Runner-->>CI_Workflow: report job results
    CI_Workflow-->>GitHub: update status / PR checks
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

I hopped through lines and linted tracks,
A workflow sewn to watch our stacks.
Types are tidy, tests run true,
Loops bounded, formats checked anew.
🐇✨

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f876cb1 and 04df078.

📒 Files selected for processing (2)
  • .github/workflows/ci-common.yml (1 hunks)
  • common/src/util/algos.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • common/src/util/algos.ts
  • .github/workflows/ci-common.yml
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🔭 Outside diff range comments (2)
common/src/util/parse.ts (1)

55-56: Ternary precedence bug produces wrong output

'[embed]' + node.attrs.src ? ... is parsed as ('[embed]' + node.attrs.src) ? ..., so the condition is always truthy (even when src is undefined) and the [embed] prefix is lost. Wrap the ternary operand in parentheses:

-      '[embed]' + node.attrs.src ? `(${node.attrs.src})` : '',
+      '[embed]' + (node.attrs.src ? `(${node.attrs.src})` : ''),
common/src/love/lover.ts (1)

7-10: Handle potential Supabase query errors

run() may return { error, data }. The current implementation ignores error and blindly accesses data[0], which will throw if data is null. Propagate or handle the error to avoid runtime failures.

-  const res = await run(db.from('lovers').select('*').eq('user_id', userId))
-  return res.data[0]
+  const { data, error } = await run(
+    db.from('lovers').select('*').eq('user_id', userId)
+  )
+  if (error) throw error
+  return data?.[0] ?? null
🧹 Nitpick comments (5)
common/src/util/parse.ts (1)

5-5: Remove commented-out import instead of leaving dead code

The Node import was unused and correctly removed, but leaving it commented clutters the file. Delete the line entirely to keep the import section clean.

-  //Node,
common/src/love/lover.ts (1)

3-3: Delete commented-out Database import

If the type is no longer required, remove the comment entirely; if it is required elsewhere, restore the proper import. Commented imports add noise and risk drifting out of date.

-//import { Database } from 'common/supabase/schema'
common/src/util/json.ts (1)

3-5: Parsing '' always throws – consider 'null' instead

Using '' as the default causes JSON.parse to throw every time the input is falsy, relying on the catch block for normal control flow. Parsing 'null' avoids the exception and is slightly cheaper.

-    return JSON.parse(json ?? '')
+    return JSON.parse(json ?? 'null')
common/src/api/schema.ts (1)

39-39: Follow TypeScript naming conventions for type aliases.

Type aliases should use PascalCase according to TypeScript conventions.

-type apiTypeCheck = { [x: string]: APIGenericSchema }
+type APITypeCheck = { [x: string]: APIGenericSchema }

And update the usage:

-export const API: apiTypeCheck = {
+export const API: APITypeCheck = {
.github/workflows/ci-common.yml (1)

15-27: Consider optimizing the duplicated setup steps.

All four jobs repeat identical setup steps (checkout, node setup, yarn install, dependencies). This creates maintenance overhead and longer CI times.

Consider using a composite action or job matrix to reduce duplication:

+  setup:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - uses: actions/setup-node@v4
+        with:
+          node-version: '18'
+          cache: 'yarn'
+      - run: npm install -g yarn
+      - run: yarn install --frozen-lockfile
+  
   test:
     runs-on: ubuntu-latest
+    needs: setup
     steps:
-      - uses: actions/checkout@v4
-      - uses: actions/setup-node@v4
-        with:
-          cache: 'yarn'
-      - name: Install yarn
-        run: npm install -g yarn
-      - name: Install dependencies
-        run: yarn
       - name: Run tests
         run: yarn test

Also consider:

  1. Pinning Node.js version (e.g., node-version: '18')
  2. Using --frozen-lockfile for reproducible builds

Also applies to: 28-40, 41-53, 54-66

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b6f1237 and f876cb1.

📒 Files selected for processing (19)
  • .github/workflows/ci-common.yml (1 hunks)
  • common/eslint.config.mjs (1 hunks)
  • common/jest.config.js (1 hunks)
  • common/package.json (2 hunks)
  • common/src/api/schema.ts (2 hunks)
  • common/src/api/websocket-client.ts (1 hunks)
  • common/src/api/zod-types.ts (0 hunks)
  • common/src/envs/is-prod.ts (1 hunks)
  • common/src/love/lover.ts (1 hunks)
  • common/src/secrets.ts (1 hunks)
  • common/src/socials.test.ts (4 hunks)
  • common/src/util/algos.ts (1 hunks)
  • common/src/util/api.ts (1 hunks)
  • common/src/util/json.ts (1 hunks)
  • common/src/util/parse.ts (1 hunks)
  • common/src/util/random.ts (1 hunks)
  • common/src/util/string.ts (1 hunks)
  • common/tsconfig.js (1 hunks)
  • common/tsconfig.json (1 hunks)
💤 Files with no reviewable changes (1)
  • common/src/api/zod-types.ts
🧰 Additional context used
🧬 Code Graph Analysis (2)
common/src/socials.test.ts (1)
common/src/socials.ts (2)
  • strip (22-23)
  • getSocialUrl (72-73)
common/src/util/api.ts (1)
common/src/api/utils.ts (1)
  • getApiUrl (34-39)
🔇 Additional comments (16)
common/src/util/random.ts (1)

54-55: LGTM – newline only

Only a trailing newline was added; no functional impact.

common/src/api/websocket-client.ts (1)

89-102: Good cleanup of unused parameter

Removing the unused _ev parameter silences ESLint without altering behaviour.

common/src/api/schema.ts (1)

41-479: LGTM! Excellent refactoring to address ESLint warnings.

The conversion from an unused variable to a proper type alias effectively resolves the ESLint warning while maintaining type safety. The as const assertion at the end properly preserves literal types for better type inference.

common/tsconfig.js (1)

1-22: tsconfig.js and tsconfig.json are in sync ✅

The key compiler options (target, module, strict) in common/tsconfig.js match those in common/tsconfig.json. This workaround is solid for Jest/Prettier compatibility and aligns with your PR objectives.

• No mismatches found in key settings.
• Composite project configuration and path mappings look correct.

Suggestion: Add a brief comment at the top of common/tsconfig.js (or a CI validation step) pointing to common/tsconfig.json to remind future maintainers to keep them aligned.

common/src/util/string.ts (1)

7-8: LGTM! Good practice to ensure consistent file endings.

Adding the newline at the end of the file follows standard formatting conventions and helps maintain consistency across the codebase.

common/src/secrets.ts (1)

94-94: LGTM! Clean code improvement by removing unused error parameter.

Since the caught error was not being used (the catch block throws a new error with a custom message), removing the unused parameter follows best practices and likely addresses ESLint warnings.

common/tsconfig.json (1)

16-18: LGTM! Beneficial TypeScript configuration improvements.

The addition of resolveJsonModule and esModuleInterop compiler options enhances module compatibility and aligns with the ES module migration described in the PR objectives.

common/src/util/api.ts (1)

18-18: Approve type safety change but verify numeric path formatting

The String(path) cast correctly ensures getApiUrl always receives a string, covering both string and number inputs without runtime errors.

APIPath is defined as keyof typeof API in common/src/api/schema.ts:481
• No instances of numeric literals passed to typedAPICall were found—ensure any dynamic numeric segments (e.g., IDs) don’t require custom formatting (zero-padding, prefixes, etc.) beyond the default String() conversion.

common/src/envs/is-prod.ts (1)

1-2: LGTM! Proper ES module migration.

Converting from dynamic require to static import aligns with the ES module migration and improves static analysis capabilities.

common/src/socials.test.ts (1)

26-28: LGTM! Improved test readability.

The multi-line formatting for long expected values enhances readability without changing test logic.

Also applies to: 37-39, 48-53, 59-61, 63-65, 74-76, 77-79, 80-82, 83-85, 86-88, 89-91, 92-94, 99-101, 105-107, 108-110

common/package.json (1)

3-3: LGTM! Enables ES module support.

Setting "type": "module" properly configures the package for ES module usage, aligning with the broader migration.

common/jest.config.js (2)

5-12: Export syntax and configuration look correct.

The conversion from module.exports to export default is properly implemented, and the usage of tsconfig.compilerOptions.paths aligns with the imported module structure.


2-3: tsconfig.js presence and structure verified

The common/tsconfig.js file exists and correctly exports a default object with compilerOptions.paths. The original common/tsconfig.json remains intact for reference. No further changes needed—LGTM.

common/eslint.config.mjs (2)

1-10: Modern ESLint flat config setup looks good.

The imports, file patterns, and use of recommended configurations are appropriate. The combination of browser and node globals makes sense for a common library that might run in different environments.


11-17: Investigate the no-unused-expressions rule error rather than disabling it

The comment in common/eslint.config.mjs (around lines 13–17) indicates a “Cannot read properties of undefined” failure coming from the @typescript-eslint/no-unused-expressions rule—this points to a configuration or version mismatch, not a style choice. Please reproduce the error in your local environment, identify whether it’s caused by parserOptions, plugin loading, or a plugin bug, and restore the rule to “error” once the root cause is addressed.

• File: common/eslint.config.mjs
Lines: ~13–17 – don’t leave @typescript-eslint/no-unused-expressions turned off; reproduce the error locally and update your ESLint config or plugin version to fix it
• Steps you might try:
– Ensure parser, parserOptions, and plugins are correctly set for TypeScript files
– Confirm you’re on a compatible @typescript-eslint version or upgrade/downgrade as needed
– Run ESLint directly in a local shell (not via Yarn’s sandbox) to see the full stack trace and pinpoint the failing code path

.github/workflows/ci-common.yml (1)

3-9: Path-based triggering is well configured.

The workflow correctly triggers only for changes in the common directory while excluding documentation files. This ensures efficient CI runs.

Comment thread .github/workflows/ci-common.yml Outdated
Comment thread common/package.json
"zod": "3.21.4"
},
"devDependencies": {
"@eslint/js": "9.32.0",
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify ESLint dependency versions for compatibility and security.

The ESLint-related dependencies look reasonable, but ensure these versions are compatible with each other and free from known vulnerabilities.

Also applies to: 33-34, 37-38


🏁 Script executed:

#!/bin/bash
# Description: Check for compatibility issues and security advisories for ESLint dependencies

# Check for npm audit issues with the new dependencies
echo "Checking for security vulnerabilities..."
npm audit --package-lock-only --audit-level=moderate

# Verify ESLint and typescript-eslint compatibility
echo "Checking ESLint version compatibility..."
curl -s https://registry.npmjs.org/typescript-eslint/8.39.0 | jq '.peerDependencies.eslint'

Length of output: 697


🏁 Script executed:

#!/bin/bash
# List all ESLint-related devDependencies and their versions
echo "ESLint-related devDependencies in common/package.json:"
jq -r '.devDependencies 
  | to_entries[] 
  | select(.key | test("eslint")) 
  | "\(.key)@\(.value)"'

echo
# For each, fetch its peerDependencies.eslint requirement
echo "peerDependencies.eslint for each:"
for dep in $(jq -r '.devDependencies | keys[] | select(test("eslint"))' common/package.json); do
  version=$(jq -r ".devDependencies[\"$dep\"]" common/package.json)
  requirement=$(curl -s "https://registry.npmjs.org/$dep/$version" \
    | jq -r '.peerDependencies.eslint // "none"')
  echo "$dep@$version$requirement"
done

Length of output: 1505


ESLint dependencies compatibility confirmed; add a lockfile for security auditing

  • common/package.json devDependencies:
    • eslint@9.32.0
    • @eslint/js@9.32.0
    • typescript-eslint@8.39.0 → requires eslint ^8.57.0 || ^9.0.0 (9.32.0 satisfies this)
  • No other ESLint-related peer dependencies detected.
  • A lockfile is missing, so npm audit cannot run. Please generate a package-lock.json (e.g. npm i --package-lock-only) and rerun npm audit --audit-level=moderate to surface any vulnerabilities.

Also applies to: lines 33–34, 37–38

🤖 Prompt for AI Agents
In common/package.json around lines 29, 33-34, and 37-38, ESLint-related
dependencies versions are compatible, but there is no lockfile present. Generate
a package-lock.json by running `npm i --package-lock-only` in the common
directory, then rerun `npm audit --audit-level=moderate` to identify any
vulnerabilities and ensure security auditing is enabled.

Comment thread common/src/util/algos.ts Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant