pierre-review 0.1.72 → 0.1.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/sync/upsert.js +47 -1
- package/package.json +1 -1
package/dist/sync/upsert.js
CHANGED
|
@@ -45,11 +45,57 @@ export function createUserResolver() {
|
|
|
45
45
|
const cached = cache.get(login);
|
|
46
46
|
if (cached !== undefined)
|
|
47
47
|
return cached;
|
|
48
|
+
const nodeId = actor?.id ?? null;
|
|
49
|
+
// The GitHub node id is the STABLE identity; the login is NOT. The same
|
|
50
|
+
// account can surface under two different logins — even inside one sync
|
|
51
|
+
// payload: a bot's Bot-typed author field reads `dependabot[bot]` while its
|
|
52
|
+
// commit-author field reads the bare `dependabot`, both carrying the same
|
|
53
|
+
// node id; and humans get renamed. Because BOTH `github_login` AND
|
|
54
|
+
// `github_node_id` are UNIQUE, the login-keyed upsert below is unsafe when a
|
|
55
|
+
// DIFFERENT row already owns this node id: matching the login (or inserting a
|
|
56
|
+
// new one) while `coalesce`-stamping the node raises "UNIQUE constraint
|
|
57
|
+
// failed: users.github_node_id". So when we have a node id, resolve on it
|
|
58
|
+
// FIRST and reuse the row that owns it — the colliding insert/update is never
|
|
59
|
+
// issued. Only a brand-new (or absent) node id falls through to the
|
|
60
|
+
// login-keyed upsert, where stamping the node can't collide.
|
|
61
|
+
if (nodeId) {
|
|
62
|
+
const owner = (await exec
|
|
63
|
+
.select({
|
|
64
|
+
id: users.id,
|
|
65
|
+
isBot: users.isBot,
|
|
66
|
+
isBotOverridden: users.isBotOverridden,
|
|
67
|
+
})
|
|
68
|
+
.from(users)
|
|
69
|
+
.where(eq(users.githubNodeId, nodeId))
|
|
70
|
+
.limit(1)
|
|
71
|
+
.execute())[0];
|
|
72
|
+
if (owner) {
|
|
73
|
+
// Refresh volatile metadata but NEVER rewrite the login: the row already
|
|
74
|
+
// holds a canonical login for this node id, and rewriting it would risk the
|
|
75
|
+
// github_login UNIQUE (when the incoming login belongs to another live row)
|
|
76
|
+
// and thrash a bot that alternates login forms across a single sync. Only
|
|
77
|
+
// set fields the actor actually carries (a commit-author resolve has no
|
|
78
|
+
// name/avatar/typename) so we never clobber a known value with null — the
|
|
79
|
+
// same "coalesce" intent as the upsert below, via plain portable value
|
|
80
|
+
// binds (a raw `sql` boolean can't bind on sqlite; a bare null param can
|
|
81
|
+
// confuse pg type inference). isBot honours a manual override.
|
|
82
|
+
const set = { isBot: owner.isBotOverridden ? owner.isBot : isLikelyBot(login) };
|
|
83
|
+
if (actor?.name != null)
|
|
84
|
+
set.displayName = actor.name;
|
|
85
|
+
if (actor?.avatarUrl != null)
|
|
86
|
+
set.avatarUrl = actor.avatarUrl;
|
|
87
|
+
if (actor?.__typename != null)
|
|
88
|
+
set.githubType = actor.__typename;
|
|
89
|
+
await exec.update(users).set(set).where(eq(users.id, owner.id)).execute();
|
|
90
|
+
cache.set(login, owner.id);
|
|
91
|
+
return owner.id;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
48
94
|
const row = (await exec
|
|
49
95
|
.insert(users)
|
|
50
96
|
.values({
|
|
51
97
|
githubLogin: login,
|
|
52
|
-
githubNodeId:
|
|
98
|
+
githubNodeId: nodeId,
|
|
53
99
|
displayName: actor?.name ?? null,
|
|
54
100
|
avatarUrl: actor?.avatarUrl ?? null,
|
|
55
101
|
// GraphQL __typename ('User'|'Bot'|…) when the actor carried it (the fat
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pierre-review",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.73",
|
|
4
4
|
"description": "Dashboard for tracking your team's GitHub PR activity across repos — local (SQLite + gh) or self-hosted multi-tenant cloud (Postgres + GitHub App).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Alex Wakeman",
|