Skip to content

Commit 7fd4fa5

Browse files
authored
Merge branch 'linode:develop' into develop
2 parents e343821 + dec6b50 commit 7fd4fa5

File tree

13 files changed

+98
-24
lines changed

13 files changed

+98
-24
lines changed

.github/workflows/coverage.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ jobs:
4747
path: ref_code_coverage.txt
4848

4949
current_branch:
50-
if: github.event.pull_request.draft == false
50+
# We want to make sure we only run on open PRs (not drafts), but also should run even if the base branch coverage job fails.
51+
# If the base branch coverage job fails to create a report, the current branch coverage job will fail as well, but this may help us debug the CI on the current branch.
52+
if: ${{ always() && github.event.pull_request.draft == false }}
5153
runs-on: ubuntu-latest
5254
needs: base_branch
5355

docs/tooling/analytics.md

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
# Adobe Analytics
1+
# Analytics
2+
3+
## Adobe Analytics
24

35
Cloud Manager uses Adobe Analytics to capture page view and custom event statistics. To view analytics, Cloud Manager developers must follow internal processes to request access to Adobe Analytics dashboards.
46

5-
## Writing a Custom Event
7+
### Writing a Custom Event
68

79
Custom events live (mostly) in `src/utilities/analytics/customEventAnalytics.ts`. Try to write and export custom events in this file if possible, and import them in the component(s) where they are used.
810

911
A custom event will take this shape:
12+
1013
```tsx
1114
// Component.tsx {file(s) where the event is called, for quick reference}
1215
// OtherComponent.tsx
@@ -33,7 +36,7 @@ Examples
3336
- `sendMarketplaceSearchEvent` fires when selecting a category from the dropdown (`label` is predefined) and clicking the search field (a generic `label` is used).
3437
- `sendBucketCreateEvent` sends the region of the bucket, but does not send the bucket label.
3538

36-
## Writing Form Events
39+
### Writing Form Events
3740

3841
Form events differ from custom events because they track user's journey through a flow and, optionally, branching flows. Form events live in `src/utilities/analytics/formEventAnalytics.ts`. Try to write and export custom events in this file if possible, and import them in the component(s) where they are used.
3942

@@ -53,10 +56,34 @@ These are the form events we use:
5356

5457
See the `LinodeCreateForm` form events as an example.
5558

56-
## Locally Testing Page Views & Custom Events and/or Troubleshooting
59+
### Locally Testing Page Views & Custom Events and/or Troubleshooting Adobe Analytics
5760

5861
1. Set the `REACT_APP_ADOBE_ANALYTICS_URL` environment variable in `.env`.
5962
2. Use the browser tools Network tab, filter requests by "adobe", and check that successful network requests have been made to load the launch script and its extensions.
6063
3. In the browser console, type `_satellite.setDebug(true)`.
6164
4. Refresh the page. You should see Adobe debug log output in the console. Each page view change or custom event that fires should be visible in the logs.
6265
5. When viewing dashboards in Adobe Analytics, it may take ~1 hour for analytics data to update. Once this happens, locally fired events will be visible in the dev dashboard.
66+
67+
## Pendo
68+
69+
Cloud Manager uses [Pendo](https://www.pendo.io/pendo-for-your-customers/) to capture analytics, guide users, and improve the user experience. To view Pendo dashboards, Cloud Manager developers must follow internal processes to request access.
70+
71+
### Set Up and Initialization
72+
73+
Pendo is configured in [`usePendo.js`](https://github.com/linode/manager/blob/develop/packages/manager/src/hooks/usePendo.ts). This custom hook allows us to initialize the Pendo analytics script when the [App](https://github.com/linode/manager/blob/develop/packages/manager/src/App.tsx#L56) is mounted.
74+
75+
Important notes:
76+
77+
- Pendo is only loaded if a valid `PENDO_API_KEY` is configured as an environment variable. In our development, staging, and production environments, `PENDO_API_KEY` is available at build time. See **Locally Testing Page Views & Custom Events and/or Troubleshooting Pendo** for set up with local environments.
78+
- We load the Pendo agent from the CDN, rather than [self-hosting](https://support.pendo.io/hc/en-us/articles/360038969692-Self-hosting-the-Pendo-agent).
79+
- We are hashing account and visitor IDs in a way that is consistent with Akamai's standards.
80+
- At initialization, we do string transformation on select URL patterns to **remove sensitive data**. When new URL patterns are added to Cloud Manager, verify that existing transforms remove sensitive data; if not, update the transforms.
81+
- Pendo is currently not using any client-side (cookies or local) storage.
82+
- Pendo makes use of the existing `data-testid` properties, used in our automated testing, for tagging elements. They are more persistent and reliable than CSS properties, which are liable to change.
83+
84+
### Locally Testing Page Views & Custom Events and/or Troubleshooting Pendo
85+
86+
1. Set the `REACT_APP_PENDO_API_KEY` environment variable in `.env`.
87+
2. Use the browser tools Network tab, filter requests by "pendo", and check that successful network requests have been made to load Pendo scripts. (Also visible in browser tools Sources tab.)
88+
3. In the browser console, type `pendo.validateEnvironment()`.
89+
4. You should see command output in the console, and it should include a hashed `accountId` and hashed `visitorId`. Each page view change or custom event that fires should be visible as a request in the Network tab.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/api-v4": Fixed
3+
---
4+
5+
Incorrect documentation on how to set a page size ([#11129](https://github.com/linode/manager/pull/11129))

packages/api-v4/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ pagination and filter parameters to the API:
141141

142142
```js
143143
// Return page 2 of Linodes, with a page size of 100:
144-
getLinodes({ page: 2, pageSize: 100 });
144+
getLinodes({ page: 2, page_size: 100 });
145145

146146
// Return all public Linode Images:
147147
getImages({}, { is_public: true });
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Added
3+
---
4+
5+
Pendo documentation to our development guide ([#11122](https://github.com/linode/manager/pull/11122))
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/manager": Fixed
3+
---
4+
5+
Flaky DatabaseBackups.test.tsx in coverage job ([#11130](https://github.com/linode/manager/pull/11130))

packages/manager/src/features/Databases/DatabaseDetail/DatabaseBackups/DatabaseBackups.test.tsx

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { waitFor } from '@testing-library/react';
12
import * as React from 'react';
23

34
import {
@@ -6,7 +7,7 @@ import {
67
profileFactory,
78
} from 'src/factories';
89
import { makeResourcePage } from 'src/mocks/serverHandlers';
9-
import { http, HttpResponse, server } from 'src/mocks/testServer';
10+
import { HttpResponse, http, server } from 'src/mocks/testServer';
1011
import { formatDate } from 'src/utilities/formatDate';
1112
import { renderWithTheme } from 'src/utilities/testHelpers';
1213

@@ -19,7 +20,6 @@ describe('Database Backups', () => {
1920
});
2021
const backups = databaseBackupFactory.buildList(7);
2122

22-
// Mock the Database because the Backups Details page requires it to be loaded
2323
server.use(
2424
http.get('*/profile', () => {
2525
return HttpResponse.json(profileFactory.build({ timezone: 'utc' }));
@@ -32,15 +32,34 @@ describe('Database Backups', () => {
3232
})
3333
);
3434

35-
const { findByText } = renderWithTheme(<DatabaseBackups />);
35+
const { findAllByText, getByText, queryByText } = renderWithTheme(
36+
<DatabaseBackups />
37+
);
38+
39+
// Wait for loading to disappear
40+
await waitFor(() =>
41+
expect(queryByText(/loading/i)).not.toBeInTheDocument()
42+
);
43+
44+
await waitFor(
45+
async () => {
46+
const renderedBackups = await findAllByText((content) => {
47+
return /\d{4}-\d{2}-\d{2}/.test(content);
48+
});
49+
expect(renderedBackups).toHaveLength(backups.length);
50+
},
51+
{ timeout: 5000 }
52+
);
3653

37-
for (const backup of backups) {
38-
// Check to see if all 7 backups are rendered
39-
expect(
40-
// eslint-disable-next-line no-await-in-loop
41-
await findByText(formatDate(backup.created, { timezone: 'utc' }))
42-
).toBeInTheDocument();
43-
}
54+
await waitFor(
55+
() => {
56+
backups.forEach((backup) => {
57+
const formattedDate = formatDate(backup.created, { timezone: 'utc' });
58+
expect(getByText(formattedDate)).toBeInTheDocument();
59+
});
60+
},
61+
{ timeout: 5000 }
62+
);
4463
});
4564

4665
it('should render an empty state if there are no backups', async () => {

packages/manager/src/features/Linodes/LinodeCreate/Security.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { inputMaxWidth } from '@linode/ui';
21
import React from 'react';
32
import { Controller, useFormContext, useWatch } from 'react-hook-form';
43

@@ -56,7 +55,11 @@ export const Security = () => {
5655
Security
5756
</Typography>
5857
<React.Suspense
59-
fallback={<Skeleton sx={{ height: '89px', maxWidth: inputMaxWidth }} />}
58+
fallback={
59+
<Skeleton
60+
sx={(theme) => ({ height: '89px', maxWidth: theme.inputMaxWidth })}
61+
/>
62+
}
6063
>
6164
<Controller
6265
render={({ field, fieldState }) => (

packages/manager/src/features/Linodes/LinodeCreate/VPC/VPC.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { inputMaxWidth } from '@linode/ui';
21
import React, { useState } from 'react';
32
import { Controller, useFormContext, useWatch } from 'react-hook-form';
43

@@ -133,7 +132,9 @@ export const VPC = () => {
133132
}}
134133
textFieldProps={{
135134
sx: (theme) => ({
136-
[theme.breakpoints.up('sm')]: { minWidth: inputMaxWidth },
135+
[theme.breakpoints.up('sm')]: {
136+
minWidth: theme.inputMaxWidth,
137+
},
137138
}),
138139
tooltipText: REGION_CAVEAT_HELPER_TEXT,
139140
}}

packages/manager/src/hooks/usePendo.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ const hashUniquePendoId = (id: string | undefined) => {
3030
};
3131

3232
/**
33-
* Initializes our Pendo analytics script on mount.
33+
* Initializes our Pendo analytics script on mount if a valid `PENDO_API_KEY` exists.
3434
*/
3535
export const usePendo = () => {
3636
const { data: account } = useAccount();
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@linode/ui": Changed
3+
---
4+
5+
Moved `inputMaxWidth` into `Theme` ([#11116](https://github.com/linode/manager/pull/11116))

packages/ui/src/foundations/themes/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { deepmerge } from '@mui/utils';
33

44
// Themes & Brands
55
import { darkTheme } from './dark';
6-
import { lightTheme, inputMaxWidth as _inputMaxWidth } from './light';
6+
import { lightTheme } from './light';
77

88
import type {
99
ChartTypes,
@@ -77,6 +77,7 @@ declare module '@mui/material/styles/createTheme' {
7777
color: Colors;
7878
font: Fonts;
7979
graphs: any;
80+
inputMaxWidth: number;
8081
inputStyles: any;
8182
interactionTokens: InteractionTypes;
8283
name: ThemeName;
@@ -97,6 +98,7 @@ declare module '@mui/material/styles/createTheme' {
9798
color?: DarkModeColors | LightModeColors;
9899
font?: Fonts;
99100
graphs?: any;
101+
inputMaxWidth?: number;
100102
inputStyles?: any;
101103
interactionTokens?: InteractionTypes;
102104
name: ThemeName;
@@ -106,6 +108,5 @@ declare module '@mui/material/styles/createTheme' {
106108
}
107109
}
108110

109-
export const inputMaxWidth = _inputMaxWidth;
110111
export const light = createTheme(lightTheme);
111112
export const dark = createTheme(deepmerge(lightTheme, darkTheme));

packages/ui/src/foundations/themes/light.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { latoWeb } from '../fonts';
1515

1616
import type { ThemeOptions } from '@mui/material/styles';
1717

18-
export const inputMaxWidth = 416;
18+
const inputMaxWidth = 416;
1919

2020
export const bg = {
2121
app: Color.Neutrals[5],
@@ -1526,6 +1526,7 @@ export const lightTheme: ThemeOptions = {
15261526
},
15271527
yellow: `rgba(255, 220, 125, ${graphTransparency})`,
15281528
},
1529+
inputMaxWidth,
15291530
inputStyles: {
15301531
default: {
15311532
backgroundColor: Select.Default.Background,

0 commit comments

Comments
 (0)