Skip to content

feat: use email as main tracking field - #2700

Merged
thisisnithin merged 24 commits into
mainfrom
ale/eng-8365-enable-email-level-breakdown-for-custom-events-in-posthog
Apr 15, 2026
Merged

thisisnithin merged 24 commits into
mainfrom
ale/eng-8365-enable-email-level-breakdown-for-custom-events-in-posthog

Conversation

@alepane21

@alepane21 alepane21 commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

Currently we track by organization slug.
To get more sense from the data, we should separate data by email and group them by organization id. This will help us to have the best use of PostHog.

Be careful that:

  • I had to add to the whoami endpoint the organizationId
  • I've compiled the proto, but to do that I also upgraded the protoc-gen-go to v1.36.10 in the Makefile, to align to the one used by the router
    • so you will see a lot of changes in the protobuf go code, but there is almost nothing there, just the new organizationId field

Summary by CodeRabbit

  • Chores
    • Improved telemetry to return a structured identity object, consistently capture organization and user identifiers, and use a safer anonymous fallback with clearer debug logging on errors.
    • Enhanced tracking behavior to prefer stable email-based identities, assign users to organization groups, and link prior anonymous identifiers to new email identities to preserve analytics continuity.

Checklist

  • I have discussed my proposed changes in an issue and have received approval to proceed.
  • I have followed the coding standards of the project.
  • Tests or benchmarks have been added or updated.
  • Documentation has been updated on https://github.com/wundergraph/docs-website.
  • I have read the Contributors Guide.

Open Source AI Manifesto

This project follows the principles of the Open Source AI Manifesto. Please ensure your contribution aligns with its principles.

@coderabbitai

coderabbitai Bot commented Mar 27, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

CLI telemetry now returns a structured TelemetryIdentity from apiClient.platform.whoAmI() (falling back to { organizationSlug: 'anonymous' } and logging errors) and uses it for distinctId and orgslug groups. Studio PostHog identification now prefers email, handles existing distinctId cases, and assigns orgslug group.

Changes

Cohort / File(s) Summary
CLI telemetry identity restructuring
cli/src/core/telemetry.ts
Added TelemetryIdentity type; getIdentity now returns Promise<TelemetryIdentity> and derives identity only from apiClient.platform.whoAmI() when available (removed getLoginDetails().organizationSlug). On missing client/error/non-OK responses it returns { organizationSlug: 'anonymous' } and logs via console.debug. capture now sets distinctId = identity.userEmail ?? identity.organizationSlug and groups = { orgslug: identity.organizationSlug }.
Studio PostHog identification flow
studio/src/lib/track.ts
identify now reads posthog.get_distinct_id() and branches: if distinctId strictly equals email it returns early; if distinctId loosely equals organizationSlug it aliases to email and resets the session; otherwise it calls posthog.identify(email, {...}) and sets posthog.group('orgslug', organizationSlug).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title directly and accurately summarizes the main change: switching the primary tracking field from organization-based identification to email-based identification, which is reflected in both modified files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

This comment has been minimized.

@codecov

codecov Bot commented Mar 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 13.72549% with 132 lines in your changes missing coverage. Please review.
✅ Project coverage is 40.69%. Comparing base (0a880bd) to head (e7b2a3b).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...to/wg/cosmo/graphqlmetrics/v1/graphqlmetrics.pb.go 16.66% 44 Missing and 1 partial ⚠️
...to/wg/cosmo/graphqlmetrics/v1/graphqlmetrics.pb.go 16.66% 36 Missing and 9 partials ⚠️
studio/src/lib/track.ts 0.00% 20 Missing ⚠️
cli/src/core/telemetry.ts 5.26% 18 Missing ⚠️
...lplane/src/core/bufservices/organization/whoAmI.ts 0.00% 2 Missing ⚠️
...phqlmetrics/gen/proto/wg/cosmo/common/common.pb.go 50.00% 1 Missing ⚠️
router/gen/proto/wg/cosmo/common/common.pb.go 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##            main    #2700       +/-   ##
==========================================
+ Coverage   1.59%   40.69%   +39.10%     
==========================================
  Files        296      999      +703     
  Lines      41501   124268    +82767     
  Branches     432     5589     +5157     
==========================================
+ Hits         662    50573    +49911     
- Misses     40553    71956    +31403     
- Partials     286     1739     +1453     
Files with missing lines Coverage Δ
router/gen/proto/wg/cosmo/node/v1/node.pb.go 28.89% <ø> (ø)
...phqlmetrics/gen/proto/wg/cosmo/common/common.pb.go 27.94% <50.00%> (ø)
router/gen/proto/wg/cosmo/common/common.pb.go 48.52% <50.00%> (ø)
...lplane/src/core/bufservices/organization/whoAmI.ts 6.06% <0.00%> (ø)
cli/src/core/telemetry.ts 8.60% <5.26%> (ø)
studio/src/lib/track.ts 0.00% <0.00%> (ø)
...to/wg/cosmo/graphqlmetrics/v1/graphqlmetrics.pb.go 11.95% <16.66%> (ø)
...to/wg/cosmo/graphqlmetrics/v1/graphqlmetrics.pb.go 16.32% <16.66%> (ø)

... and 696 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cli/src/core/telemetry.ts (1)

5-5: ⚠️ Potential issue | 🟡 Minor

Remove the unused getLoginDetails import.

The getLoginDetails function is imported on line 5 but is not used anywhere in this file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/src/core/telemetry.ts` at line 5, Remove the unused import
getLoginDetails from the import statement that currently reads "import { config,
getBaseHeaders, getLoginDetails } ..." — edit the import to only include the
used symbols (config and getBaseHeaders) and run the linter/TypeScript check to
ensure no other references to getLoginDetails remain in this module.
🧹 Nitpick comments (4)
cli/src/core/telemetry.ts (2)

145-148: console.debug output may be unintended in production.

Unlike the other error handlers that check process.env.DEBUG, this console.debug call will always output to stderr. Consider gating it behind the DEBUG check for consistency.

♻️ Proposed fix
   } catch (err) {
     // skip catch, returning anonymous identity if any error occurs (e.g. network issues, not logged in, etc.)
-    console.debug('Failed to get identity for telemetry, using anonymous.', err)
+    if (process.env.DEBUG) {
+      console.debug('Failed to get identity for telemetry, using anonymous.', err);
+    }
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/src/core/telemetry.ts` around lines 145 - 148, The catch block in
telemetry.ts currently uses console.debug(...) unconditionally; change it to
only log when DEBUG is enabled (same pattern used elsewhere) by guarding the
console.debug call with a check like if (process.env.DEBUG) before logging, so
the "Failed to get identity for telemetry, using anonymous." message is only
printed in debug mode; update the catch in the function that retrieves identity
for telemetry (the catch that currently calls console.debug with the err) to
follow this conditional logging pattern.

33-36: Consider using interface instead of type for object shapes.

Per coding guidelines, interfaces are preferred over type aliases for object shapes.

♻️ Proposed fix
-type TelemetryIdentity = {
+interface TelemetryIdentity {
   userEmail?: string;
   organizationSlug: string;
-}
+}

As per coding guidelines: "Prefer interfaces over type aliases for object shapes in TypeScript".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/src/core/telemetry.ts` around lines 33 - 36, Replace the type alias
TelemetryIdentity with an equivalent interface declaration to follow the
project's TypeScript guideline preferring interfaces for object shapes; locate
the TelemetryIdentity type and change it to an interface (keeping the same
property names and optional marker userEmail?: and organizationSlug) and update
any imports/uses if necessary to reference the interface name unchanged.
studio/src/lib/track.ts (2)

51-52: Stale comment no longer reflects the implementation.

The comment states "We use the id posthog sets to identify the user" but the code now uses email as the primary identifier, not the PostHog-generated distinct ID.

📝 Proposed fix
   // Identify with PostHog
-  // We use the id posthog sets to identify the user. This way we do not lose cross domain tracking.
+  // We use email as the primary identifier and alias old session IDs to maintain cross-domain tracking.
   const posthog = PostHogClient();
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@studio/src/lib/track.ts` around lines 51 - 52, Update the stale comment in
studio/src/lib/track.ts to reflect the current implementation: replace "We use
the id posthog sets to identify the user" with a description stating that the
code uses the user's email as the primary identifier when calling PostHog (e.g.,
in the identify/track logic that references email and PostHog client), and
remove any mention of relying on PostHog's generated distinct_id so the comment
matches the actual behavior.

7-11: Remove dead window.ko declaration and avoid any types.

Per retrieved learnings, window.ko (Koala tracking) is dead code and should be removed. Additionally, using any type violates TypeScript guidelines.

♻️ Proposed fix
 declare global {
   interface Window {
-    ko: any;
-    Reo: any;
+    Reo: {
+      identify: (params: { username: string; type: string }) => void;
+    };
   }
 }

Based on learnings: "In studio/src/lib/track.ts, remove all references to window.ko (Koala tracking) as it is no longer used."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@studio/src/lib/track.ts` around lines 7 - 11, Remove the dead Koala
declaration by deleting the window.ko entry from the global Window interface in
studio/src/lib/track.ts, and replace the use of the any type for window.Reo with
a safer type: either declare Reo?: unknown on Window or create a minimal
ReoClient interface (e.g., methods you call) and use Reo?: ReoClient; also scan
this file for any other uses of any related to tracking and replace them with
proper types or unknown to avoid using any.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cli/src/core/telemetry.ts`:
- Around line 140-143: The WhoAmIResponse currently returns userEmail as an
empty string which causes identity.userEmail ?? identity.organizationSlug in
capture() to treat it as a valid value; update the function that constructs the
identity object to normalize empty userEmail to null/undefined (e.g., set
userEmail to resp.userEmail?.trim() || undefined) so that capture() will fall
back to organizationSlug; locate references to WhoAmIResponse and the identity
return (userEmail and organizationSlug) in telemetry.ts and ensure the
normalized value is used by capture().

In `@studio/src/lib/track.ts`:
- Around line 64-67: Replace the loose comparison and add a null/undefined
guard: retrieve distinctId via posthog.get_distinct_id() and only call
posthog.alias(email, distinctId) when distinctId is defined (not undefined/null)
and not equal to email using strict inequality (distinctId !== email); update
the condition around the alias call that currently references distinctId and
email to perform these checks before invoking posthog.alias.
- Line 63: Add the missing semicolon at the end of the posthog.group('orgslug',
organizationSlug) statement in track.ts so the expression terminates correctly;
locate the usage of posthog.group in the file and append a semicolon to the
statement.

---

Outside diff comments:
In `@cli/src/core/telemetry.ts`:
- Line 5: Remove the unused import getLoginDetails from the import statement
that currently reads "import { config, getBaseHeaders, getLoginDetails } ..." —
edit the import to only include the used symbols (config and getBaseHeaders) and
run the linter/TypeScript check to ensure no other references to getLoginDetails
remain in this module.

---

Nitpick comments:
In `@cli/src/core/telemetry.ts`:
- Around line 145-148: The catch block in telemetry.ts currently uses
console.debug(...) unconditionally; change it to only log when DEBUG is enabled
(same pattern used elsewhere) by guarding the console.debug call with a check
like if (process.env.DEBUG) before logging, so the "Failed to get identity for
telemetry, using anonymous." message is only printed in debug mode; update the
catch in the function that retrieves identity for telemetry (the catch that
currently calls console.debug with the err) to follow this conditional logging
pattern.
- Around line 33-36: Replace the type alias TelemetryIdentity with an equivalent
interface declaration to follow the project's TypeScript guideline preferring
interfaces for object shapes; locate the TelemetryIdentity type and change it to
an interface (keeping the same property names and optional marker userEmail?:
and organizationSlug) and update any imports/uses if necessary to reference the
interface name unchanged.

In `@studio/src/lib/track.ts`:
- Around line 51-52: Update the stale comment in studio/src/lib/track.ts to
reflect the current implementation: replace "We use the id posthog sets to
identify the user" with a description stating that the code uses the user's
email as the primary identifier when calling PostHog (e.g., in the
identify/track logic that references email and PostHog client), and remove any
mention of relying on PostHog's generated distinct_id so the comment matches the
actual behavior.
- Around line 7-11: Remove the dead Koala declaration by deleting the window.ko
entry from the global Window interface in studio/src/lib/track.ts, and replace
the use of the any type for window.Reo with a safer type: either declare Reo?:
unknown on Window or create a minimal ReoClient interface (e.g., methods you
call) and use Reo?: ReoClient; also scan this file for any other uses of any
related to tracking and replace them with proper types or unknown to avoid using
any.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 95eaad94-affc-4b89-9505-b3857a3e4c83

📥 Commits

Reviewing files that changed from the base of the PR and between d5e14cc and f7425da.

📒 Files selected for processing (2)
  • cli/src/core/telemetry.ts
  • studio/src/lib/track.ts

Comment thread cli/src/core/telemetry.ts
Comment thread studio/src/lib/track.ts Outdated
Comment thread studio/src/lib/track.ts Outdated
alepane21 and others added 3 commits April 3, 2026 10:02
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
cli/src/core/telemetry.ts (1)

140-143: ⚠️ Potential issue | 🟡 Minor

Normalize empty userEmail before returning identity.

At Line 142, an empty string is preserved, so identity.userEmail ?? identity.organizationSlug can still produce an empty distinctId.

🔧 Proposed fix
     if (resp.response?.code === EnumStatusCode.OK) {
       return {
         organizationSlug: resp.organizationSlug,
-        userEmail: resp.userEmail,
+        userEmail: resp.userEmail?.trim() || undefined,
       };
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/src/core/telemetry.ts` around lines 140 - 143, The returned identity
currently preserves an empty string in userEmail which causes downstream
`identity.userEmail ?? identity.organizationSlug` to still pick an empty value;
in the return object (the block that sets organizationSlug:
resp.organizationSlug, userEmail: resp.userEmail) normalize userEmail by
treating empty or whitespace-only strings as undefined (e.g., trim and set to
undefined/null) so that downstream logic using `identity.userEmail ??
identity.organizationSlug` will correctly fall back to organizationSlug.
🧹 Nitpick comments (1)
cli/src/core/telemetry.ts (1)

33-36: Use an interface for TelemetryIdentity object shape.

The TypeScript guideline requires interfaces over type aliases for object shapes.

♻️ Proposed change
-type TelemetryIdentity = {
+interface TelemetryIdentity {
   userEmail?: string;
   organizationSlug: string;
-};
+}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cli/src/core/telemetry.ts` around lines 33 - 36, Replace the type alias
TelemetryIdentity with an interface declaration (interface TelemetryIdentity {
userEmail?: string; organizationSlug: string; }) so the object shape uses an
interface per project TypeScript guidelines; update any imports/usages that
reference TelemetryIdentity if necessary to reflect the new declaration but keep
the same property names and optionality.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cli/src/core/telemetry.ts`:
- Around line 145-148: The catch block that currently calls
console.debug('Failed to get identity for telemetry, using anonymous.', err)
should not log unconditionally; update the catch in the telemetry identity
retrieval function (the try/catch that gets identity for telemetry) to only emit
that debug output when debugging is enabled (e.g. guard with process.env.DEBUG
or the module's debug flag) or use the existing debug logger API instead of
unconditional console.debug so no error details are printed in normal CLI runs.

---

Duplicate comments:
In `@cli/src/core/telemetry.ts`:
- Around line 140-143: The returned identity currently preserves an empty string
in userEmail which causes downstream `identity.userEmail ??
identity.organizationSlug` to still pick an empty value; in the return object
(the block that sets organizationSlug: resp.organizationSlug, userEmail:
resp.userEmail) normalize userEmail by treating empty or whitespace-only strings
as undefined (e.g., trim and set to undefined/null) so that downstream logic
using `identity.userEmail ?? identity.organizationSlug` will correctly fall back
to organizationSlug.

---

Nitpick comments:
In `@cli/src/core/telemetry.ts`:
- Around line 33-36: Replace the type alias TelemetryIdentity with an interface
declaration (interface TelemetryIdentity { userEmail?: string; organizationSlug:
string; }) so the object shape uses an interface per project TypeScript
guidelines; update any imports/usages that reference TelemetryIdentity if
necessary to reflect the new declaration but keep the same property names and
optionality.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f91a2449-e5e7-4690-be06-05254ac11314

📥 Commits

Reviewing files that changed from the base of the PR and between e6e1a0b and deea4fe.

📒 Files selected for processing (2)
  • cli/src/core/telemetry.ts
  • studio/src/lib/track.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • studio/src/lib/track.ts

Comment thread cli/src/core/telemetry.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
studio/src/lib/track.ts (1)

53-54: ⚠️ Potential issue | 🟡 Minor

Use const and strict equality for distinctId check.

distinctId is never reassigned, and the loose comparison can coerce types unexpectedly.

🔧 Proposed fix
-  let distinctId = posthog.get_distinct_id();
-  if (distinctId == organizationSlug) {
+  const distinctId = posthog.get_distinct_id();
+  if (distinctId === organizationSlug) {
As per coding guidelines: "Prefer `const` over `let` and `let` over `var`" and "Always use strict equality (`===` and `!==`) instead of loose equality (`==` and `!=`)".
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@studio/src/lib/track.ts` around lines 53 - 54, Replace the mutable
declaration and loose comparison: change the declaration of distinctId (from
posthog.get_distinct_id()) to use const instead of let, and update the equality
check to use strict equality (===) when comparing distinctId to
organizationSlug; locate this in the block that calls posthog.get_distinct_id()
and the subsequent if (distinctId == organizationSlug) check and update the
variable declaration and comparison accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@studio/src/lib/track.ts`:
- Around line 61-64: The early return when distinctId === email in track.ts
prevents executing posthog.identify(...) and posthog.group('orgslug',
organizationSlug'), leaving org grouping and profile properties stale; remove or
alter that early return so that even when distinctId === email you still call
posthog.identify(...) (or at minimum call posthog.group('orgslug',
organizationSlug') and trigger the profile refresh logic) after the
duplicate-check, ensuring the org grouping and user profile update paths run
(refer to distinctId, email, posthog.identify, posthog.group, and the profile
refresh code in track.ts).

---

Duplicate comments:
In `@studio/src/lib/track.ts`:
- Around line 53-54: Replace the mutable declaration and loose comparison:
change the declaration of distinctId (from posthog.get_distinct_id()) to use
const instead of let, and update the equality check to use strict equality (===)
when comparing distinctId to organizationSlug; locate this in the block that
calls posthog.get_distinct_id() and the subsequent if (distinctId ==
organizationSlug) check and update the variable declaration and comparison
accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 98eb7c95-1fc6-4642-a80b-6737604dfe35

📥 Commits

Reviewing files that changed from the base of the PR and between e806527 and 83e86c7.

📒 Files selected for processing (1)
  • studio/src/lib/track.ts

Comment thread studio/src/lib/track.ts
@alepane21
alepane21 marked this pull request as ready for review April 3, 2026 09:44
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

github-actions Bot commented Apr 7, 2026

Copy link
Copy Markdown

Router image scan passed

✅ No security vulnerabilities found in image:

ghcr.io/wundergraph/cosmo/router:sha-6c882dadebf14f3c7a2e15f4f8f82aa8da7eeca2

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@alepane21
alepane21 requested review from a team as code owners April 8, 2026 07:35
@alepane21
alepane21 requested a review from thisisnithin April 8, 2026 07:50

@endigma endigma left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

good

@thisisnithin
thisisnithin merged commit 23fc31d into main Apr 15, 2026
83 of 85 checks passed
@thisisnithin
thisisnithin deleted the ale/eng-8365-enable-email-level-breakdown-for-custom-events-in-posthog branch April 15, 2026 09:06
@coderabbitai coderabbitai Bot mentioned this pull request May 5, 2026
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants