Skip to content

Stabilize collaboration E2E tests and update dependencies#5

Merged
parazeeknova merged 4 commits intomainfrom
dev
Mar 20, 2026
Merged

Stabilize collaboration E2E tests and update dependencies#5
parazeeknova merged 4 commits intomainfrom
dev

Conversation

@parazeeknova
Copy link
Copy Markdown
Owner

  1. apps/web/.env — Port fix
    Changed NEXT_PUBLIC_COLLAB_WS_URL from port 4000 to 4001 to match the E2E collab server.
  2. apps/web/src/platform/phoenix/socket-client.ts
  • Exported getActiveConnection so the controller can check if the Phoenix socket is alive (used to detect HMR vs real sign-out)
  • Added process.env.NEXT_PUBLIC_COLLAB_WS_URL direct check in getCollabWebSocketUrl() to work around Turbopack not inlining env vars accessed via @t3-oss/env-nextjs's runtimeEnv object literal
  1. apps/web/src/platform/env/env-diagnostics.ts
  • Added direct property access for NEXT_PUBLIC_COLLAB_WS_URL in readOptionOrEnv() — Turbopack can't inline computed process.env[variable] access
  1. apps/web/src/features/workbook/store/workbook-store-controller.ts
  • Imported getActiveConnection from socket-client
  • Auth handler fix: When !user, checks getActiveConnection() before disconnecting. If the socket is still alive (HMR), skips disconnect for non-shared sessions
  • connectRealtimeSession race fix: Stores realtimeConnectPromise synchronously BEFORE the async IIFE starts, preventing concurrent calls from bypassing the guard
  • Added isActiveSession check after persistActiveWorkbookMeta: Prevents setting "connected" on a stale session
  • destroyActiveWorkbookSession fix: Clears realtimeConnectPromise so subsequent connectRealtimeSession calls don't reuse a stale promise
  • handleDocUpdate fix: Removed moduleState.currentAuthenticatedUser guard on sendSync so guest editors can broadcast their edits
  1. apps/web/src/features/workbook/routes/hooks/use-workbook-route-session.ts
  • Fixed closure bug: The openedSessionId variable was shared across StrictMode effect re-runs. The first run's cleanup would close the SECOND run's session (because openedSessionId was overwritten). Fixed by only closing if activeSessionId is set at cleanup time
  1. apps/web/src/features/workbook/collaboration/lib/workbook-realtime-channel-client.ts
  • Cleaned up debug console.info statements from notifyStatus, onError, onClose, disconnect, and sendSnapshot
  • Removed duplicate channel.onClose handler that was causing double "disconnected" status events
  1. apps/web/e2e/workbook-editor-sync.e2e.ts
  • Fixed substring → slice lint issue
  1. scripts/run-e2e.ts
  • Changed to --workers=1 for sequential test execution
    Root Causes Found
  1. Turbopack env var bug: @t3-oss/env-nextjs reads process.env.NEXT_PUBLIC_* via runtimeEnv object literals. Turbopack replaces these with undefined in the browser bundle. Fixed by adding direct process.env.NEXT_PUBLIC_COLLAB_WS_URL access as fallback.
  2. React StrictMode double-mount: StrictMode mounts → cleans up → remounts. The cleanup in useWorkbookRouteSession destroyed the session AFTER it connected, because the openedSessionId closure variable was overwritten between effect runs.
  3. connectRealtimeSession race condition: The realtimeConnectPromise was set AFTER the async IIFE started, creating a window where concurrent calls bypassed the guard. Fixed by storing the promise synchronously.
  4. HMR auth handler: When HMR resets moduleState.currentAuthenticatedUser to null, the auth handler disconnected active connections. Fixed by checking if the Phoenix socket is still alive.

…ervability

Increase timeouts and add detailed logging across the collaboration stack to resolve flakiness in synchronization tests. Automate environment configuration for E2E runs and refine socket connection persistence logic.
Upgrade external libraries including Next.js, Firebase, and TanStack while synchronizing internal package versions across the monorepo.
…ent variable handling

Resolve race conditions in realtime connection logic and ensure environment variables are correctly inlined for Turbopack. Limit E2E test concurrency and remove verbose logging to improve overall synchronization stability.
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
papyrus-sheets Ready Ready Preview, Comment Mar 20, 2026 0:45am

@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Stabilize collaboration E2E tests, fix realtime race conditions, and resolve Turbopack env var issues

🐞 Bug fix 🧪 Tests ✨ Enhancement

Grey Divider

Walkthroughs

Description
• Stabilize E2E tests with improved timeouts, error handling, and sequential execution
  - Added detailed error logging and browser error capture in createDocument
  - Increased collaboration connection timeouts from 15s to 90s
  - Changed Playwright to sequential execution (workers=1) instead of parallel
  - Enhanced helper functions with explicit waits and popover animations
• Fix race conditions and HMR issues in realtime collaboration
  - Store realtimeConnectPromise synchronously before async operations to prevent concurrent
  connection bypasses
  - Check Phoenix socket liveness before disconnecting on auth state changes to preserve HMR
  connections
  - Fix closure bug in useWorkbookRouteSession where cleanup destroyed wrong session
  - Allow guest editors to broadcast edits by removing authenticated user guard
• Resolve Turbopack environment variable inlining issues
  - Add direct process.env.NEXT_PUBLIC_COLLAB_WS_URL access as fallback in socket client and env
  diagnostics
  - Automate E2E environment configuration via .env.local generation in test runner
• Improve observability with enhanced logging across collaboration stack
  - Add structured logging to Phoenix socket connection lifecycle
  - Add console logging for auth state and collaboration status changes
  - Add browser console message filtering in E2E tests for debugging
• Update dependencies across monorepo
  - Bump Next.js, Firebase, TanStack, PostHog, and other libraries
  - Synchronize internal package versions
Diagram
flowchart LR
  A["E2E Test Helpers"] -->|"Add timeouts & error handling"| B["Test Stability"]
  C["Playwright Config"] -->|"Sequential execution"| B
  D["Socket Client"] -->|"Direct env access & logging"| E["Turbopack Compatibility"]
  F["Realtime Connection"] -->|"Sync promise storage"| G["Race Condition Fixes"]
  H["Auth Handler"] -->|"Check socket liveness"| G
  I["Route Session Hook"] -->|"Fix closure bug"| G
  J["Doc Update Handler"] -->|"Allow guest broadcasts"| G
  K["Env Diagnostics"] -->|"Direct property access"| E
  L["Test Runner Script"] -->|"Generate .env.local"| E
  M["Dependencies"] -->|"Update versions"| N["Monorepo Sync"]
Loading

Grey Divider

File Changes

1. apps/web/e2e/helpers.ts 🧪 Tests +67/-15

Enhanced E2E helpers with timeouts and error handling

apps/web/e2e/helpers.ts


2. apps/web/e2e/workbook-collaboration.e2e.ts 🧪 Tests +4/-4

Increased collaboration connection timeouts in tests

apps/web/e2e/workbook-collaboration.e2e.ts


3. apps/web/e2e/workbook-editor-sync.e2e.ts 🧪 Tests +21/-9

Added logging and increased sync polling timeouts

apps/web/e2e/workbook-editor-sync.e2e.ts


View more (16)
4. apps/web/playwright.config.ts ⚙️ Configuration changes +2/-1

Disabled parallel execution for sequential test runs

apps/web/playwright.config.ts


5. apps/web/src/features/workbook/collaboration/lib/workbook-realtime-channel-client.ts ✨ Enhancement +22/-5

Enhanced logging for realtime channel connection lifecycle

apps/web/src/features/workbook/collaboration/lib/workbook-realtime-channel-client.ts


6. apps/web/src/features/workbook/routes/hooks/use-workbook-route-session.ts 🐞 Bug fix +8/-12

Fixed closure bug in session cleanup logic

apps/web/src/features/workbook/routes/hooks/use-workbook-route-session.ts


7. apps/web/src/features/workbook/store/workbook-store-controller.ts 🐞 Bug fix +176/-139

Fixed race conditions and HMR auth handling in realtime sessions

apps/web/src/features/workbook/store/workbook-store-controller.ts


8. apps/web/src/features/workbook/store/workbook-store.ts ✨ Enhancement +20/-3

Added collaboration status logging instrumentation

apps/web/src/features/workbook/store/workbook-store.ts


9. apps/web/src/platform/auth/auth-client.ts ✨ Enhancement +12/-2

Added debug logging for stub auth session reading

apps/web/src/platform/auth/auth-client.ts


10. apps/web/src/platform/env/env-diagnostics.ts 🐞 Bug fix +7/-0

Direct property access for Turbopack env var inlining

apps/web/src/platform/env/env-diagnostics.ts


11. apps/web/src/platform/phoenix/socket-client.ts 🐞 Bug fix +88/-21

Store connection globally, add logging, fix Turbopack env inlining

apps/web/src/platform/phoenix/socket-client.ts


12. packages/logs/src/index.ts 🐞 Bug fix +4/-0

Fixed development environment detection for browser context

packages/logs/src/index.ts


13. scripts/run-e2e.ts ✨ Enhancement +38/-2

Automate E2E environment configuration and sequential test execution

scripts/run-e2e.ts


14. apps/collab/mix.exs Dependencies +1/-1

Bump collaboration server version to 0.1.15

apps/collab/mix.exs


15. apps/collab/package.json Dependencies +1/-1

Bump collaboration package version to 0.1.15

apps/collab/package.json


16. apps/web/package.json Dependencies +12/-12

Update Next.js, Firebase, TanStack, and other dependencies

apps/web/package.json


17. package.json Dependencies +9/-9

Update dev dependencies and fix turbo command syntax

package.json


18. packages/core/package.json Dependencies +2/-2

Bump core package version and update yjs dependency

packages/core/package.json


19. packages/logs/package.json Dependencies +1/-1

Bump logs package version

packages/logs/package.json


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Mar 20, 2026

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 📐 Spec deviations (0)

Grey Divider


Action required

1. instrumentedSet console.info logging📘 Rule violation ⚙ Maintainability
Description
The store wrapper logs collaborationStatus via console.info on state updates, which is a debug
artifact in production client code. This can leak internal state transitions and adds noise to user
consoles.
Code

apps/web/src/features/workbook/store/workbook-store.ts[R21-25]

+      if (next && "collaborationStatus" in next) {
+        console.info(
+          `[INFO][workbook-store] collaborationStatus → ${next.collaborationStatus}`
+        );
+      }
Evidence
PR Compliance ID 7 forbids debug artifacts like console logging in production code; the PR adds a
console.info(...) call in the client-side workbook store.

AGENTS.md
apps/web/src/features/workbook/store/workbook-store.ts[12-26]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`console.info` logging was introduced in the client workbook store (`instrumentedSet`) to print `collaborationStatus` changes. Compliance requires no debug console logging in production code paths.
## Issue Context
This runs in a `"use client"` module and will execute for real users, not just E2E runs.
## Fix Focus Areas
- apps/web/src/features/workbook/store/workbook-store.ts[12-27]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. auth-client adds console.info📘 Rule violation ⛨ Security
Description
Stub auth code now logs session lookup results and parse errors using console.info, including user
identifiers. This violates the no-debug-artifacts requirement and may leak information to browser
consoles.
Code

apps/web/src/platform/auth/auth-client.ts[R172-188]

 if (!storedSession) {
+    console.info(
+      `[auth-client] readStoredStubUser: no session found for key "${E2E_AUTH_SESSION_STORAGE_KEY}"`
+    );
   return null;
 }

 try {
   const parsedSession = JSON.parse(storedSession) as E2EAuthSessionPayload;
-    return buildStubUser(parsedSession);
-  } catch {
+    const user = buildStubUser(parsedSession);
+    console.info(`[auth-client] readStoredStubUser: found user ${user.uid}`);
+    return user;
+  } catch (error) {
+    console.info(`[auth-client] readStoredStubUser: parse error ${error}`);
   return null;
 }
}
Evidence
PR Compliance ID 7 prohibits console logging in production code; the PR introduces multiple
console.info(...) statements in the auth client implementation.

AGENTS.md
apps/web/src/platform/auth/auth-client.ts[172-210]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`console.info` statements were added to `readStoredStubUser()` and `getCurrentAuthUser()`. This is a debug artifact and can expose auth/session details in the browser console.
## Issue Context
Even if primarily used for stub/E2E auth, this code is part of the shipped web bundle and should not emit console logs by default.
## Fix Focus Areas
- apps/web/src/platform/auth/auth-client.ts[172-210]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. runConnect swallows connection errors📘 Rule violation ⛯ Reliability
Description
runConnect() catches errors and only calls rejectConnect(error) without rethrowing, so `await
runConnect()` can succeed even when the realtime connection fails. This risks leaving the UI in an
incorrect state (e.g., stuck as connecting) and hides failures from callers.
Code

apps/web/src/features/workbook/store/workbook-store-controller.ts[R969-971]

+      } catch (error) {
+        rejectConnect(error);
+      }
Evidence
PR Compliance ID 4 requires correct async error handling; the added catch block rejects the stored
promise but does not rethrow, effectively swallowing the error for the initiating call path that
awaits runConnect().

AGENTS.md
apps/web/src/features/workbook/store/workbook-store-controller.ts[854-981]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`connectRealtimeSession()` creates `connectPromise` and stores it in `session.realtimeConnectPromise`, but the `runConnect()` implementation catches and does not rethrow errors. As a result, the first caller (`await runConnect()`) may not observe failures.
## Issue Context
The intended behavior is: (1) store an in-flight promise synchronously to prevent concurrent connects, and (2) ensure errors propagate to the initiating caller and update state appropriately.
## Fix Focus Areas
- apps/web/src/features/workbook/store/workbook-store-controller.ts[843-981]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (3)
4. Prod logs always enabled🐞 Bug ➹ Performance
Description
isDevelopmentEnv() returns true whenever window exists, which forces createLogger() to
always log to the browser console even in production builds. This changes production behavior,
increases client overhead, and can expose internal operational details to end users.
Code

packages/logs/src/index.ts[R27-30]

+  if (typeof window !== "undefined") {
+    return true;
+  }
+
Evidence
The logger writes to console only when isDevelopmentEnv() is true; the new browser branch returns
true unconditionally. Existing tests explicitly expect no console writes when NODE_ENV is production
(but those tests run in Node and won’t catch the browser-only regression).

packages/logs/src/index.ts[26-72]
packages/logs/src/index.test.ts[83-111]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The logging library treats all browser environments as development (`typeof window !== "undefined" => true`), causing production clients to emit console logs.
### Issue Context
`writeLog()` uses `isDevelopmentEnv()` to decide whether to write to console vs only forward to sinks.
### Fix Focus Areas
- packages/logs/src/index.ts[26-72]
### Suggested change
Make the browser branch also check the environment (e.g., `process.env.NODE_ENV === "development"`) rather than returning `true` unconditionally. Ensure bundlers can still inline the value if needed.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


5. Token exposed on window🐞 Bug ⛨ Security
Description
ensurePhoenixSocketConnection stores the Firebase ID token on the PhoenixSocketConnection object and
persists that object on window for HMR reuse. This makes the token directly readable by any script
executing in the page context via the global window key.
Code

apps/web/src/platform/phoenix/socket-client.ts[R175-237]

+    try {
+      const currentUser = assertSignedInUser(uid);
+      token = await currentUser.getIdToken();
+      params = {
+        ...params,
+        token,
+      };
+      phoenixLogger.info("Connecting as authenticated user", {
+        uid,
+        hasToken: !!token,
+        tokenLength: token?.length,
+      });
+    } catch (error) {
+      phoenixLogger.error("Failed to get auth token", { error });
+      throw error;
+    }
 }

+  const existingConnection = getActiveConnection();
 if (
-    activeConnection &&
-    activeConnection.isGuest === isGuest &&
-    activeConnection.uid === uid &&
-    activeConnection.token === token
+    existingConnection &&
+    existingConnection.isGuest === isGuest &&
+    existingConnection.uid === uid &&
+    existingConnection.token === token
 ) {
-    return activeConnection;
+    phoenixLogger.info("Reusing existing socket connection");
+    return existingConnection;
 }

+  phoenixLogger.info("Creating new socket connection...", { collabUrl });
 disconnectPhoenixSocket();

+  const wsTransport = typeof WebSocket === "undefined" ? undefined : WebSocket;
+
 const nextConnection: PhoenixSocketConnection = {
   deviceId,
   isGuest,
   socket: new Socket(collabUrl, {
     params,
     timeout: PHOENIX_CHANNEL_TIMEOUT_MS,
+      ...(wsTransport ? { transport: wsTransport } : {}),
   }),
   token,
   uid,
 };

+  phoenixLogger.info("Connecting socket...");
 nextConnection.socket.connect();
+
 nextConnection.socket.onClose(() => {
-    if (activeConnection?.socket === nextConnection.socket) {
-      activeConnection = null;
+    phoenixLogger.info("Phoenix socket closed");
+    const current = getActiveConnection();
+    if (current?.socket === nextConnection.socket) {
+      setActiveConnection(null);
   }
 });
+
 nextConnection.socket.onError((error: unknown) => {
-    phoenixLogger.warn("Phoenix socket error.", error);
+    phoenixLogger.error("Phoenix socket error.", error);
 });

-  activeConnection = nextConnection;
+  setActiveConnection(nextConnection);
 return nextConnection;
Evidence
The code fetches token = await currentUser.getIdToken(), stores it on nextConnection.token, and
then calls setActiveConnection(nextConnection) which assigns the full object to
window[GLOBAL_CONNECTION_KEY]. That globally exposes the credential at runtime.

apps/web/src/platform/phoenix/socket-client.ts[163-237]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A Firebase ID token is stored on a connection object that is saved on `window`, exposing a credential to any in-page script.
### Issue Context
The global window storage was introduced to survive module reloads/HMR.
### Fix Focus Areas
- apps/web/src/platform/phoenix/socket-client.ts[163-237]
### Suggested change
Keep the socket on `window` if needed for HMR, but do not persist the token there. Options:
- Remove `token` from the globally stored object (store it only in a module-local variable or closure).
- Store only non-sensitive fields on `window` (socket, deviceId, uid/isGuest), and adjust the reuse check to avoid token equality checks, or compare a non-sensitive token fingerprint if absolutely necessary.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. E2E env file clobbered🐞 Bug ⛯ Reliability
Description
The E2E runner overwrites ./apps/web/.env.local and then unconditionally deletes it during
cleanup, risking loss of a developer’s existing local configuration. It also calls bunWrite(...)
without awaiting completion, creating a race where the dev server may start before the file is
written.
Code

scripts/run-e2e.ts[R227-255]

+const ENV_LOCAL_PATH = "./apps/web/.env.local";
+
+function writeE2EEnvLocal(): void {
+  const envContent = [
+    `NEXT_PUBLIC_COLLAB_WS_URL=ws://127.0.0.1:${COLLAB_PORT}/ws`,
+    "NEXT_PUBLIC_E2E_AUTH_MODE=stub",
+    `NEXT_PUBLIC_E2E_AUTH_URL=http://127.0.0.1:${COLLAB_PORT}/api/e2e/session`,
+    "NEXT_PUBLIC_FIREBASE_API_KEY=e2e-firebase-api-key",
+    "NEXT_PUBLIC_FIREBASE_APP_ID=e2e-firebase-app-id",
+    "NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN=e2e.firebaseapp.test",
+    "NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=e2e-firebase-sender-id",
+    "NEXT_PUBLIC_FIREBASE_PROJECT_ID=e2e-firebase-project-id",
+    "NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET=e2e-firebase-storage-bucket",
+    "",
+  ].join("\n");
+
+  bunWrite(ENV_LOCAL_PATH, envContent);
+  log(`${colors.dim}Wrote E2E env overrides to .env.local${colors.reset}`);
+}
+
+function removeE2EEnvLocal(): void {
+  try {
+    if (existsSync(ENV_LOCAL_PATH)) {
+      unlinkSync(ENV_LOCAL_PATH);
+    }
+  } catch {
+    // ignore cleanup errors
+  }
+}
Evidence
writeE2EEnvLocal writes to a fixed .env.local path and cleanup removes the same path if it exists,
without checking whether it was pre-existing. The write call is not awaited, even though it’s an
async API in Bun.

scripts/run-e2e.ts[227-255]
scripts/run-e2e.ts[257-341]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`scripts/run-e2e.ts` overwrites and deletes `apps/web/.env.local` without backup, and does not await the write.
### Issue Context
This script can be run locally and should not destroy a developer’s existing `.env.local`.
### Fix Focus Areas
- scripts/run-e2e.ts[227-255]
- scripts/run-e2e.ts[257-341]
### Suggested change
- Before writing, detect whether `.env.local` exists; if it does, back it up (e.g., `.env.local.e2e-backup`) and restore it in cleanup.
- Make `writeE2EEnvLocal` async and `await bunWrite(...)` (or use `writeFileSync`) before spawning the web server.
- Only delete `.env.local` in cleanup if the script created it (e.g., via a sentinel comment/marker or backup presence).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

7. getActiveConnection unsafe window cast📘 Rule violation ⚙ Maintainability
Description
getActiveConnection() and setActiveConnection() use chained type assertions on window and then
cast the stored value to PhoenixSocketConnection | null. This is an unsafe typing escape hatch
that can mask incorrect values at runtime.
Code

apps/web/src/platform/phoenix/socket-client.ts[R30-32]

+  return (window as unknown as Record<string, unknown>)[
+    GLOBAL_CONNECTION_KEY
+  ] as PhoenixSocketConnection | null;
Evidence
PR Compliance ID 2 requires type-safe and explicit TypeScript; the PR introduces unsafe `as unknown
as ... and as PhoenixSocketConnection | null` assertions for global state storage.

AGENTS.md
apps/web/src/platform/phoenix/socket-client.ts[24-41]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The Phoenix socket connection is stored on `window` using `as unknown as Record&amp;lt;string, unknown&amp;gt;` and then cast back to `PhoenixSocketConnection | null`. This is unsafe and bypasses type checking.
## Issue Context
Prefer adding a typed global augmentation for `Window` (or a dedicated module-level singleton) so reads/writes are type-safe without `unknown` casts.
## Fix Focus Areas
- apps/web/src/platform/phoenix/socket-client.ts[24-41]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Comment thread apps/web/src/features/workbook/store/workbook-store.ts Outdated
Comment thread apps/web/src/platform/auth/auth-client.ts
Comment thread apps/web/src/features/workbook/store/workbook-store-controller.ts
Comment thread packages/logs/src/index.ts
Comment thread apps/web/src/platform/phoenix/socket-client.ts
Comment thread scripts/run-e2e.ts
…ration stability

Prevent sensitive token exposure in global state and ensure original environment files are restored after E2E runs. Remove redundant debug logging and refine environment detection for browser bundles.
@parazeeknova parazeeknova merged commit b045069 into main Mar 20, 2026
5 checks passed
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