Skip to content

Commit

Permalink
Release v1.106.0 - staging → master
Browse files Browse the repository at this point in the history
Merge pull request #9850 from linode/staging
  • Loading branch information
carrillo-erik authored Oct 30, 2023
2 parents 60f2729 + 88d7ddd commit c40386d
Show file tree
Hide file tree
Showing 390 changed files with 7,478 additions and 3,919 deletions.
1 change: 1 addition & 0 deletions .github/workflows/e2e_schedule_and_push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ env:
USER_3: ${{ secrets.USER_3 }}
USER_4: ${{ secrets.USER_4 }}
CLIENT_ID: ${{ secrets.REACT_APP_CLIENT_ID }}
CY_TEST_FAIL_ON_MANAGED: 1
on:
schedule:
- cron: "0 13 * * 1-5"
Expand Down
43 changes: 29 additions & 14 deletions docs/development-guide/02-component-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,59 +7,74 @@ The basic structure of a component file should follow:
```
[ imports ]
[ types and interfaces ]
[ function component definition ]
[ styles ]
[ utility functions ]
[ default export ]
[ exported function component definition ]
[ styles ] (possibly in their own file)
[ utility functions ] (possibly in their own file)
```

Here is a minimal code example demonstrating the basic structure of a component file:

```tsx
import * as React from "react";
import { styled } from "@mui/material/styles";
import { isPropValid } from "src/utilities/isPropValid";
import { omittedProps } from "src/utilities/omittedProps";

interface SayHelloProps {
// If not exported, it can just be named `Props`
export interface SayHelloProps {
name: string;
isDisabled: boolean;
}

const SayHello = (props: SayHelloProps) => {
export const SayHello = (props: SayHelloProps) => {
const { name, isDisabled } = props;

return <StyledH1 isDisabled={isDisabled}>Hello, {capitalize(name)}</StyledH1>;
};

/**
* Should be moved to SayHello.styles.ts if component was large (> 100 lines).
*/
const StyledH1 = styled("h1", {
label: "StyledH1",
shouldForwardProp: (prop) => isPropValid(["isDisabled"], prop),
shouldForwardProp: omittedProps(["isDisabled"]),
})(({ theme, ...props }) => ({
color: props.isDisabled ? theme.color.grey : theme.color.black,
}));

/**
* It's often a good idea to move utilities to their own files as well,
* either in the `src/utilities` directory if meant to be portable and reusable,
* or in the feature's directory as a .utils.ts file. ex: `SayHello.utils.ts`.
* Isolation makes utils easier to test and reduces the main file size for better readability.
* Doing so also may also reveal the use case is already covered by an existing utility.
*/
export const capitalize = (s: string) => {
return s.charAt(0).toUpperCase() + s.slice(1);
};

export { SayHello };
```

- There are cases where you don't want the prop to be forwarded to the DOM element, so we've provided a helper `isPropValid` to assist in these cases.
- The `label` property in the `styled` API is used to provide a unique identifier for the component when it is being styled. This can be useful when debugging a large codebase, as it can help identify which component the style is being applied to. For example, if you have multiple instances of the `StyledH1` component, the `label` property can help you identify which instance is being styled in the browser's developer tools.

#### Imports

- Import React with `import * as React from 'react'`.
- Use absolute imports, e.g. `import { queryClient } from 'src/queries/base'`.
- Methods from the api-v4 package should be imported from `@linode/api-v4/lib/..`.

#### Composition

When building a large component, it is recommended to break it down and avoid writing several components within the same file. It improves readability and testability. Components should, in most cases, come with their own unit test, although they can be skipped if an e2e suite is covering the functionality.
Utilities should almost always feature a unit test.

#### Styles

- With the transition to MUI v5, the [`styled`](https://mui.com/system/styled/) API, along with the [`sx` prop](https://mui.com/system/getting-started/the-sx-prop/), is the preferred way to specify component-specific styles.
- Component-specific styles may be defined at the end of the component file or in a dedicated file, named `ComponentName.styles.tsx`.
- Component-specific styles may be defined at the end of the component file or in a dedicated file, named `ComponentName.styles.ts`.
- Component files longer than 100 lines must have these styles defined in a dedicated file.

##### Styled Components
- The `label` property in the `styled` API is used to provide a unique identifier for the component when it is being styled. This can be useful when debugging a large codebase, as it can help identify which component the style is being applied to. For example, if you have multiple instances of the `StyledH1` component, the `label` property can help you identify which instance is being styled in the browser's developer tools.
- There are cases where you don't want the prop to be forwarded to the DOM element, so we've provided a helper `omittedProps` to assist in these cases.
It is the responsibility of the developer to check for any console error in case non-semantic props make their way to the dom.

#### Types and Interfaces

- To specify component props, define an interface with the name of the component `MyComponentProps` and pass it to the component as a type argument. This is to provide clarity if ever we need to export this type into another component.
Expand Down
1 change: 1 addition & 0 deletions docs/development-guide/08-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ Environment variables related to Cypress logging and reporting, as well as repor
| `CY_TEST_USER_REPORT` | Log test account information when tests begin | `1` | Unset; disabled by default |
| `CY_TEST_JUNIT_REPORT` | Enable JUnit reporting | `1` | Unset; disabled by default |
| `CY_TEST_DISABLE_FILE_WATCHING` | Disable file watching in Cypress UI | `1` | Unset; disabled by default |
| `CY_TEST_FAIL_ON_MANAGED` | Fail affected tests when Managed is enabled | `1` | Unset; disabled by default |
### Writing End-to-End Tests
Expand Down
8 changes: 8 additions & 0 deletions packages/api-v4/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## [2023-10-30] - v0.104.0

### Upcoming Features:

- Update AGLB `updateLoadbalancerServiceTarget` endpoint with method and schema ([#9800](https://github.com/linode/manager/pull/9800))
- Update AGLB `createLoadbalancerRoute` endpoint with payload/schema ([#9806](https://github.com/linode/manager/pull/9806))
- Update the `Subnet` and `Interface` interfaces to match new API spec ([#9824](https://github.com/linode/manager/pull/9824))

## [2023-10-16] - v0.103.0

### Upcoming Features:
Expand Down
2 changes: 1 addition & 1 deletion packages/api-v4/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@linode/api-v4",
"version": "0.103.0",
"version": "0.104.0",
"homepage": "https://github.com/linode/manager/tree/develop/packages/api-v4",
"bugs": {
"url": "https://github.com/linode/manager/issues"
Expand Down
21 changes: 21 additions & 0 deletions packages/api-v4/src/account/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,27 @@ export interface User {
ssh_keys: string[];
tfa_enabled: boolean;
verified_phone_number: string | null;
/**
* The date of when a password was set on a user.
* `null` if this user has not created a password yet
* @example 2022-02-09T16:19:26
* @example null
*/
password_created: string | null;
/**
* Information for the most recent login attempt for this User.
* `null` if no login attempts have been made since creation of this User.
*/
last_login: {
/**
* @example 2022-02-09T16:19:26
*/
login_datetime: string;
/**
* @example successful
*/
status: AccountLoginStatus;
} | null;
}

export interface Account {
Expand Down
8 changes: 4 additions & 4 deletions packages/api-v4/src/aglb/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import Request, {
} from '../request';
import { Filter, Params, ResourcePage } from '../types';
import { BETA_API_ROOT } from '../constants';
import type { Route, RoutePayload, UpdateRoutePayload } from './types';
import { UpdateRouteSchema } from '@linode/validation';
import type { Route, CreateRoutePayload, UpdateRoutePayload } from './types';
import { UpdateRouteSchema, CreateRouteSchema } from '@linode/validation';

/**
* getLoadbalancerRoutes
Expand Down Expand Up @@ -51,13 +51,13 @@ export const getLoadbalancerRoute = (loadbalancerId: number, routeId: number) =>
*/
export const createLoadbalancerRoute = (
loadbalancerId: number,
data: RoutePayload
data: CreateRoutePayload
) =>
Request<Route>(
setURL(
`${BETA_API_ROOT}/aglb/${encodeURIComponent(loadbalancerId)}/routes`
),
setData(data),
setData(data, CreateRouteSchema),
setMethod('POST')
);

Expand Down
9 changes: 6 additions & 3 deletions packages/api-v4/src/aglb/service-targets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import Request, {
import { Filter, Params, ResourcePage } from '../types';
import { BETA_API_ROOT } from '../constants';
import type { ServiceTarget, ServiceTargetPayload } from './types';
import { CreateServiceTargetSchema } from '@linode/validation';
import {
CreateServiceTargetSchema,
UpdateServiceTargetSchema,
} from '@linode/validation';

/**
* getLoadbalancerServiceTargets
Expand Down Expand Up @@ -84,8 +87,8 @@ export const updateLoadbalancerServiceTarget = (
loadbalancerId
)}/service-targets/${encodeURIComponent(serviceTargetId)}`
),
setData(data),
setMethod('POST')
setData(data, UpdateServiceTargetSchema),
setMethod('PUT')
);

/**
Expand Down
3 changes: 2 additions & 1 deletion packages/api-v4/src/linodes/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,14 +165,15 @@ export interface Interface {
purpose: InterfacePurpose;
ipam_address: string | null;
primary?: boolean;
active: boolean;
subnet_id?: number | null;
vpc_id?: number | null;
ipv4?: ConfigInterfaceIPv4;
ipv6?: ConfigInterfaceIPv6;
ip_ranges?: string[];
}

export type InterfacePayload = Omit<Interface, 'id'>;
export type InterfacePayload = Omit<Interface, 'id' | 'active'>;

export interface ConfigInterfaceOrderPayload {
ids: number[];
Expand Down
1 change: 1 addition & 0 deletions packages/api-v4/src/regions/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export type Capabilities =
| 'GPU Linodes'
| 'Kubernetes'
| 'Linodes'
| 'Managed Databases'
| 'Metadata'
| 'NodeBalancers'
| 'Object Storage'
Expand Down
11 changes: 10 additions & 1 deletion packages/api-v4/src/vpcs/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Interface } from 'src/linodes';

export interface VPC {
id: number;
label: string;
Expand Down Expand Up @@ -28,11 +30,18 @@ export interface CreateSubnetPayload {

export interface Subnet extends CreateSubnetPayload {
id: number;
linodes: number[];
linodes: SubnetAssignedLinodeData[];
created: string;
updated: string;
}

export interface ModifySubnetPayload {
label: string;
}

export type SubnetLinodeInterfaceData = Pick<Interface, 'active' | 'id'>;

export interface SubnetAssignedLinodeData {
id: number;
interfaces: SubnetLinodeInterfaceData[];
}
60 changes: 59 additions & 1 deletion packages/manager/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,66 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/).

## [2023-10-16] - v1.105.0
## [2023-10-30] - v1.106.0

### Added:

- October Marketplace apps ([#9771](https://github.com/linode/manager/pull/9771))
- Last log in and TFA status to Users & Grants page ([#9810](https://github.com/linode/manager/pull/9810))
- Dynamic price error handling for DC-specific pricing ([#9660](https://github.com/linode/manager/pull/9660))

### Changed:

- Linode Create error placement ([#9788](https://github.com/linode/manager/pull/9788))
- Firewall Create Drawer opens in the same tab in the Linode Create Flow ([#9785](https://github.com/linode/manager/pull/9785))

### Fixed:

- Quote variable in changeset shell command ([#9791](https://github.com/linode/manager/pull/9791))
- Primary nav DBaaS menu item flicker on page load ([#9808](https://github.com/linode/manager/pull/9808))
- Excess spacing above and below Linode CLI help text in Upload Image form ([#9812](https://github.com/linode/manager/pull/9812))
- Only show regions that support Databases on the Database Create page ([#9815](https://github.com/linode/manager/pull/9815))
- Footer styles on small viewports ([#9823](https://github.com/linode/manager/pull/9823))
- Rendering of unsanitized titles in event notification popup and support tickets ([#9826](https://github.com/linode/manager/pull/9826))
- CreateCluster form label styles and layout ([#9835](https://github.com/linode/manager/pull/9835))

### Tech Stories:

- Rename isPropValid utility ([#9790](https://github.com/linode/manager/pull/9790))
- Migrate NodeBalancer Node Mode Select TextField to Autocomplete ([#9754](https://github.com/linode/manager/pull/9754))
- Migrate UserDefinedSelect from a TextField Select to an Autocomplete ([#9756](https://github.com/linode/manager/pull/9756))
- Create Stack component ([#9830](https://github.com/linode/manager/pull/9830))
- MUI v5 Migration - `SRC > Features > StackScripts` pt1 ([#9773](https://github.com/linode/manager/pull/9773))
- Clean up `src/utilities` exports ([#9783](https://github.com/linode/manager/pull/9783))
- MUI v5 Migration - `SRC > Features > StackScripts` pt 2 ([#9786](https://github.com/linode/manager/pull/9786))
- MUI v5 Migration - `SRC > Features > Users` ([#9748](https://github.com/linode/manager/pull/9748))

### Tests:

- Improve error message display when Linode API error occurs in Cypress test ([#9777](https://github.com/linode/manager/pull/9777))
- Improve Linode config edit test stability ([#9781](https://github.com/linode/manager/pull/9781))
- Improve LKE create test reattempt stability ([#9782](https://github.com/linode/manager/pull/9782))
- Clean up Jest warnings and errors ([#9784](https://github.com/linode/manager/pull/9784))
- Fix DBaaS UI test failures stemming from API update ([#9801](https://github.com/linode/manager/pull/9801))
- Refactor Cypress Firewall migration tests ([#9807](https://github.com/linode/manager/pull/9807))
- Skip affected tests when Managed is enabled on test accounts ([#9809](https://github.com/linode/manager/pull/9809))
- Make `ConfigureForm.test.tsx` Vitest compatible ([#9816](https://github.com/linode/manager/pull/9816))

### Upcoming Features:

- Helper text for DC-specific pricing Object Storage overages ([#9813](https://github.com/linode/manager/pull/9813))
- Support VPCs in Add/Edit Linode Config dialog ([#9709](https://github.com/linode/manager/pull/9709))
- Properly support new shapes of `Subnet` and `Interface` return objects ([#9824](https://github.com/linode/manager/pull/9824))
- Only show regions that support VPCs in VPC Create page ([#9787](https://github.com/linode/manager/pull/9787))
- Invalidate VPC-related queries when deleting a Linode ([#9814](https://github.com/linode/manager/pull/9814))
- Add AGLB Routes - Rule Edit Drawer ([#9778](https://github.com/linode/manager/pull/9778))
- Add AGLB Edit Service Target drawer ([#9800](https://github.com/linode/manager/pull/9800))
- Add AGLB Rule Delete Dialog ([#9804](https://github.com/linode/manager/pull/9804))
- Add AGLB Create Route Drawer ([#9806](https://github.com/linode/manager/pull/9806))
- Add AGLB Edit Route Drawer ([#9822](https://github.com/linode/manager/pull/9822))
- Add Rule Index to AGLB Rule Table ([#9838](https://github.com/linode/manager/pull/9838))

## [2023-10-16] - v1.105.0

### Added:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ import {
databaseClusterConfiguration,
databaseConfigurations,
mockDatabaseEngineTypes,
mockDatabaseNodeTypes,
} from 'support/constants/databases';
import {
mockCreateDatabase,
mockGetDatabases,
mockGetDatabaseEngines,
mockGetDatabaseTypes,
} from 'support/intercepts/databases';
import { mockGetEvents } from 'support/intercepts/events';
import { getRegionById } from 'support/util/regions';
Expand Down Expand Up @@ -71,9 +73,10 @@ describe('create a database cluster, mocked data', () => {
);
mockCreateDatabase(databaseMock).as('createDatabase');
mockGetDatabases([databaseMock]).as('getDatabases');
mockGetDatabaseTypes(mockDatabaseNodeTypes).as('getDatabaseTypes');

cy.visitWithLogin('/databases/create');
cy.wait(['@getAccount', '@getDatabaseEngines']);
cy.wait(['@getAccount', '@getDatabaseEngines', '@getDatabaseTypes']);

ui.entityHeader
.find()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import {
mockDeleteDatabase,
mockDeleteProvisioningDatabase,
mockGetDatabase,
mockGetDatabaseTypes,
} from 'support/intercepts/databases';
import { ui } from 'support/ui';
import {
databaseClusterConfiguration,
databaseConfigurations,
mockDatabaseNodeTypes,
} from 'support/constants/databases';

describe('Delete database clusters', () => {
Expand All @@ -40,12 +42,13 @@ describe('Delete database clusters', () => {
// Mock account to ensure 'Managed Databases' capability.
mockGetAccount(accountFactory.build()).as('getAccount');
mockGetDatabase(database).as('getDatabase');
mockGetDatabaseTypes(mockDatabaseNodeTypes).as('getDatabaseTypes');
mockDeleteDatabase(database.id, database.engine).as('deleteDatabase');

cy.visitWithLogin(
`/databases/${database.engine}/${database.id}/settings`
);
cy.wait(['@getAccount', '@getDatabase']);
cy.wait(['@getAccount', '@getDatabase', '@getDatabaseTypes']);

// Click "Delete Cluster" button.
ui.button
Expand Down Expand Up @@ -97,6 +100,7 @@ describe('Delete database clusters', () => {

mockGetAccount(accountFactory.build()).as('getAccount');
mockGetDatabase(database).as('getDatabase');
mockGetDatabaseTypes(mockDatabaseNodeTypes).as('getDatabaseTypes');
mockDeleteProvisioningDatabase(
database.id,
database.engine,
Expand All @@ -106,7 +110,7 @@ describe('Delete database clusters', () => {
cy.visitWithLogin(
`/databases/${database.engine}/${database.id}/settings`
);
cy.wait(['@getAccount', '@getDatabase']);
cy.wait(['@getAccount', '@getDatabase', '@getDatabaseTypes']);

// Click "Delete Cluster" button.
ui.button
Expand Down
Loading

0 comments on commit c40386d

Please sign in to comment.