Skip to content

Commit 5525a33

Browse files
feat(cli): unify Amplitude identify flow and enforce cli event source (#478)
1 parent d28bbe6 commit 5525a33

15 files changed

Lines changed: 721 additions & 81 deletions

src/commands/auth/login.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { URL } from 'node:url';
55
import { Command } from '@oclif/core';
66
import { ensureUserSetup } from '../../api/user-setup.client.ts';
77
import { OAUTH_CALLBACK_ERROR_CODES } from '../../config/constants.ts';
8+
import { refreshIdentityFromStoredToken } from '../../service/analytics.svc.ts';
89
import { persistTokenResponse } from '../../service/auth.svc.ts';
910
import { getClientId, getRealmUrl } from '../../service/auth-config.svc.ts';
1011
import { debugLogger, getErrorMessage } from '../../service/log.svc.ts';
@@ -55,6 +56,12 @@ export default class AuthLogin extends Command {
5556
this.error(`User setup failed. ${getErrorMessage(error)}`);
5657
}
5758

59+
try {
60+
await refreshIdentityFromStoredToken();
61+
} catch (error) {
62+
this.warn(`Failed to refresh analytics identity: ${getErrorMessage(error)}`);
63+
}
64+
5865
this.log('\nLogin completed successfully.');
5966
}
6067

src/commands/auth/logout.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Command } from '@oclif/core';
2+
import { clearTrackedIdentity } from '../../service/analytics.svc.ts';
23
import { logoutFromProvider } from '../../service/auth-refresh.svc.ts';
34
import { clearStoredTokens, getStoredTokens } from '../../service/auth-token.svc.ts';
45

@@ -23,6 +24,7 @@ export default class AuthLogout extends Command {
2324
this.warn(`Failed to revoke tokens remotely: ${error instanceof Error ? error.message : error}`);
2425
}
2526

27+
clearTrackedIdentity();
2628
await clearStoredTokens();
2729
this.log('Local authentication tokens removed from your system.');
2830
}

src/commands/auth/provision-ci-token.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Command } from '@oclif/core';
22
import { provisionCIToken } from '../../api/ci-token.client.ts';
33
import { ensureUserSetup } from '../../api/user-setup.client.ts';
4+
import { refreshIdentityFromStoredToken, track } from '../../service/analytics.svc.ts';
45
import { requireAccessToken } from '../../service/auth.svc.ts';
56
import { saveCIToken } from '../../service/ci-token.svc.ts';
67
import { getErrorMessage } from '../../service/log.svc.ts';
@@ -17,10 +18,28 @@ export default class AuthProvisionCiToken extends Command {
1718
this.error(`Must be logged in to provision CI token. Run 'hd auth login' first. ${getErrorMessage(error)}`);
1819
}
1920

21+
try {
22+
await refreshIdentityFromStoredToken();
23+
} catch (error) {
24+
this.warn(`Failed to refresh analytics identity: ${getErrorMessage(error)}`);
25+
}
26+
27+
track('CLI CI Token Provision Started', (context) => ({
28+
command: 'auth provision-ci-token',
29+
app_used: context.app_used,
30+
ci_provider: context.ci_provider,
31+
cli_version: context.cli_version,
32+
started_at: context.started_at,
33+
}));
34+
2035
let orgId: number;
2136
try {
2237
orgId = await ensureUserSetup();
2338
} catch (error) {
39+
track('CLI CI Token Provision Failed', () => ({
40+
command: 'auth provision-ci-token',
41+
error: `user_setup_failed:${getErrorMessage(error)}`,
42+
}));
2443
this.error(`User setup failed. ${getErrorMessage(error)}`);
2544
}
2645

@@ -32,7 +51,14 @@ export default class AuthProvisionCiToken extends Command {
3251
this.log('');
3352
this.log('For CI/CD, set this environment variable:');
3453
this.log(` HD_CI_CREDENTIAL=${refreshToken}`);
54+
track('CLI CI Token Provision Succeeded', () => ({
55+
command: 'auth provision-ci-token',
56+
}));
3557
} catch (error) {
58+
track('CLI CI Token Provision Failed', () => ({
59+
command: 'auth provision-ci-token',
60+
error: `provision_failed:${getErrorMessage(error)}`,
61+
}));
3662
this.error(`CI token provisioning failed. ${getErrorMessage(error)}`);
3763
}
3864
}

src/hooks/finally/finally.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Hook } from '@oclif/core';
22
import ora, { type Ora } from 'ora';
33
import { track } from '../../service/analytics.svc.ts';
4+
import { debugLogger, getErrorMessage } from '../../service/log.svc.ts';
45

56
const hook: Hook<'finally'> = async (opts) => {
67
const isHelpOrVersionCmd = opts.argv.includes('--help') || opts.argv.includes('--version');
@@ -12,10 +13,14 @@ const hook: Hook<'finally'> = async (opts) => {
1213
spinner = ora().start('Cleaning up');
1314
}
1415

15-
await track('CLI Session Ended', (context) => ({
16-
cli_version: context.cli_version,
17-
ended_at: new Date(),
18-
})).promise;
16+
try {
17+
await track('CLI Session Ended', (context) => ({
18+
cli_version: context.cli_version,
19+
ended_at: new Date(),
20+
})).promise;
21+
} catch (error) {
22+
debugLogger('Failed to track CLI session end: %s', getErrorMessage(error));
23+
}
1924

2025
if (!isHelpOrVersionCmd && !hasError) {
2126
spinner?.stop();
Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,28 @@
11
import { parseArgs } from 'node:util';
22
import type { Hook } from '@oclif/core';
33
import { initializeAnalytics, track } from '../../service/analytics.svc.ts';
4+
import { debugLogger, getErrorMessage } from '../../service/log.svc.ts';
45

56
const hook: Hook.Init = async () => {
67
const args = parseArgs({ allowPositionals: true, strict: false });
7-
initializeAnalytics();
8-
track('CLI Command Submitted', (context) => ({
9-
command: args.positionals.join(' ').trim(),
10-
command_flags: Object.entries(args.values).flat().join(' '),
11-
app_used: context.app_used,
12-
ci_provider: context.ci_provider,
13-
cli_version: context.cli_version,
14-
started_at: context.started_at,
15-
}));
8+
try {
9+
await initializeAnalytics();
10+
} catch (error) {
11+
debugLogger('Failed to initialize analytics in init hook: %s', getErrorMessage(error));
12+
}
13+
14+
try {
15+
track('CLI Command Submitted', (context) => ({
16+
command: args.positionals.join(' ').trim(),
17+
command_flags: Object.entries(args.values).flat().join(' '),
18+
app_used: context.app_used,
19+
ci_provider: context.ci_provider,
20+
cli_version: context.cli_version,
21+
started_at: context.started_at,
22+
}));
23+
} catch (error) {
24+
debugLogger('Failed to track command submission: %s', getErrorMessage(error));
25+
}
1626
};
1727

1828
export default hook;

0 commit comments

Comments
 (0)