Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/cli-kit/src/private/node/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,14 @@ export async function getEnvironmentData(config: Interfaces.Config): Promise<Env
export async function getSensitiveEnvironmentData(config: Interfaces.Config) {
return {
env_plugin_installed_all: JSON.stringify(getPluginNames(config)),
env_shopify_variables: JSON.stringify(getShopifyEnvironmentVariables()),
}
}

function getShopifyEnvironmentVariables() {
return Object.fromEntries(Object.entries(process.env).filter(([key]) => key.startsWith('SHOPIFY_')))
}

function getPluginNames(config: Interfaces.Config) {
const pluginNames = [...config.plugins.keys()]
return pluginNames.sort().filter((plugin) => !plugin.startsWith('@oclif/'))
Expand Down
30 changes: 30 additions & 0 deletions packages/cli-kit/src/public/node/analytics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,36 @@ describe('event tracking', () => {
})
})

test('sends SHOPIFY_ environment variables in sensitive payload', async () => {
const originalEnv = {...process.env}
process.env.SHOPIFY_TEST_VAR = 'test_value'
process.env.SHOPIFY_ANOTHER_VAR = 'another_value'
process.env.NOT_SHOPIFY_VAR = 'should_not_appear'

await inProjectWithFile('package.json', async (args) => {
const commandContent = {command: 'dev', topic: 'app'}
await startAnalytics({commandContent, args, currentTime: currentDate.getTime() - 100})

// When
const config = {
runHook: vi.fn().mockResolvedValue({successes: [], failures: []}),
plugins: [],
} as any
await reportAnalyticsEvent({config, exitMode: 'ok'})

// Then
const sensitivePayload = publishEventMock.mock.calls[0]![2]
expect(publishEventMock).toHaveBeenCalledOnce()
expect(sensitivePayload).toHaveProperty('env_shopify_variables')
expect(sensitivePayload.env_shopify_variables).toBeDefined()

const shopifyVars = JSON.parse(sensitivePayload.env_shopify_variables as string)
expect(shopifyVars).toHaveProperty('SHOPIFY_TEST_VAR', 'test_value')
expect(shopifyVars).toHaveProperty('SHOPIFY_ANOTHER_VAR', 'another_value')
expect(shopifyVars).not.toHaveProperty('NOT_SHOPIFY_VAR')
})
})

test('does nothing when analytics are disabled', async () => {
await inProjectWithFile('package.json', async (args) => {
// Given
Expand Down
3 changes: 2 additions & 1 deletion packages/cli-kit/src/public/node/monorail.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const url = 'https://monorail-edge.shopifysvc.com/v1/produce'
type Optional<T> = T | null

// This is the topic name of the main event we log to Monorail, the command tracker
export const MONORAIL_COMMAND_TOPIC = 'app_cli3_command/1.19'
export const MONORAIL_COMMAND_TOPIC = 'app_cli3_command/1.20'

export interface Schemas {
[MONORAIL_COMMAND_TOPIC]: {
Expand All @@ -27,6 +27,7 @@ export interface Schemas {

// Environment
env_plugin_installed_all?: Optional<string>
env_shopify_variables?: Optional<string>
}
public: {
business_platform_id?: Optional<number>
Expand Down