Skip to content

Commit

Permalink
Merge pull request #10246 from linode/release-v1.114.0
Browse files Browse the repository at this point in the history
Release v1.114.0 - release → staging
  • Loading branch information
carrillo-erik authored Mar 4, 2024
2 parents 2576d32 + e07d8c7 commit 9902757
Show file tree
Hide file tree
Showing 322 changed files with 9,209 additions and 6,919 deletions.
13 changes: 5 additions & 8 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { guides } from "./plugins/sidebar";
import { generateSidebar } from "./plugins/sidebar";

export const DOCS_SRC_DIR = new URL("./../", import.meta.url).pathname;

export default {
title: "Cloud Manager Docs",
description: "Akamai Cloud Manger Documentation",
srcDir: "./",
srcDir: DOCS_SRC_DIR,
base: "/manager/",
themeConfig: {
logo: "/akamai-wave.svg",
Expand All @@ -15,12 +17,7 @@ export default {
search: {
provider: "local",
},
sidebar: [
{
text: "Development Guide",
items: guides,
},
],
sidebar: generateSidebar(DOCS_SRC_DIR),
socialLinks: [
{ icon: "github", link: "https://github.com/linode/manager" },
],
Expand Down
103 changes: 77 additions & 26 deletions docs/.vitepress/plugins/sidebar.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,89 @@
import * as fs from "fs";
import * as path from "path";
import { readdirSync } from "fs";
import { join } from "path";
import { DOCS_SRC_DIR } from "../config";

const DEVELOPMENT_GUIDE_PATH = "./docs/development-guide";
type LinkItem = { text: string; link: string };

interface MarkdownInfo {
text: string;
link: string;
type SidebarItem =
| {
text: string;
collapsed?: boolean;
items: SidebarItem[] | LinkItem[];
}
| LinkItem;

const exclude = [
"cache",
"public",
"PULL_REQUEST_TEMPLATE.md",
".vitepress",
"index.md",
];

const replacements = [
["-", " "],
["_", " "],
[".md", ""],
];

function isPathIgnored(path: string) {
for (const item of exclude) {
if (path.includes(item)) {
return true;
}
}
return false;
}

function capitalize(s: string) {
return (
s.substring(0, 1).toUpperCase() + s.substring(1, s.length).toLowerCase()
);
}

/**
* Aggregates the pages in the development-guide and populates the left sidebar.
* Given a file name, this function returns a formatted title.
*/
const scanDirectory = (directoryPath: string): MarkdownInfo[] => {
const markdownFiles = fs
.readdirSync(directoryPath)
.filter((file) => file.endsWith(".md"));
const markdownInfoArray: MarkdownInfo[] = [];
function formatSidebarItemText(fileName: string) {
// removes -, _, and .md from files names to generate the title
for (const [from, to] of replacements) {
fileName = fileName.replaceAll(from, to);
}
// Removes any number prefix. This allows us to order things by putting numbers in file names.
fileName = fileName.replace(/^[0-9]*/, "");
// Capitalizes each word in the file name
fileName = fileName.split(" ").map(capitalize).join(" ");
return fileName;
}

markdownFiles.forEach((file) => {
const filePath = path.join(directoryPath, file);
const fileContent = fs.readFileSync(filePath, "utf-8");
/**
* Generates a VitePress sidebar by recursively traversing the given directory.
*/
export function generateSidebar(dir: string) {
const files = readdirSync(dir, { withFileTypes: true });

const titleMatch = fileContent.match(/^#\s+(.*)/m);
const title = titleMatch ? titleMatch[1] : "Untitled";
const sidebar: SidebarItem[] = [];

const markdownInfo: MarkdownInfo = {
text: title,
link: `/development-guide/${file}`,
};
for (const file of files) {
const filepath = join(dir, file.name);

markdownInfoArray.push(markdownInfo);
});
if (isPathIgnored(filepath)) {
continue;
}

return markdownInfoArray;
};
if (file.isDirectory()) {
sidebar.push({
text: formatSidebarItemText(file.name),
collapsed: false,
items: generateSidebar(filepath),
});
} else {
sidebar.push({
text: formatSidebarItemText(file.name),
link: filepath.split(DOCS_SRC_DIR)[1],
});
}
}

export const guides = scanDirectory(DEVELOPMENT_GUIDE_PATH);
return sidebar;
}
6 changes: 6 additions & 0 deletions docs/.vitepress/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"compilerOptions": {
"lib": ["ESNext"],
"module": "ESNext",
}
}
6 changes: 5 additions & 1 deletion docs/development-guide/02-component-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ export const capitalize = (s: string) => {

#### 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.
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. It is also best to avoid same-file render functions (e.g. `renderTableBody`), in favor of extracting the JSX into its own component. In addition to improved readability and testability, this practice makes components less brittle and more extensible.

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
Expand All @@ -85,6 +87,8 @@ export const interface MyComponentProps {
const MyComponent = (props: MyComponentProps) { ... }
```
- When it comes to components located in the `src/features/` directory, you can use the name `Props` for their types or interfaces, unless exporting is necessary. In such cases, name the type or interface after the component name.
- Define props as required, rather than optional, as often as possible for data relying on API responses (which can be `undefined`). In the case of `undefined` props, error handling - such as early return statements - can be done in the HOC. This allows all child components to expect data, avoiding extra conditionals or convoluted logic.

#### Function Component Definition

- Prefer function components over class components.
Expand Down
10 changes: 4 additions & 6 deletions docs/development-guide/04-component-library.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Material-UI

We use [Material-UI](https://mui.com/material-ui/getting-started/overview/) as the primary component library for Cloud Manager. The library contains many UI primitives like `<Typography />` and `<Button />` as well as a layout system with the `<Grid />` component.
We use [Material-UI](https://mui.com/material-ui/getting-started/overview/) as the primary component library for Cloud Manager. The library contains many UI primitives like `<Typography />` and `<Button />`, as well as a layout system with the `<Grid />` component.

All MUI components have abstractions in the Cloud Manager codebase, meaning you will use relative imports to use them instead of importing from MUI directly:

Expand Down Expand Up @@ -37,18 +37,16 @@ A color, font, svg icon, or other simple styling convention.

##### Element

A basic HTML element wrapped in a react component, or a small component that is not normally used on its own.
A basic HTML element wrapped in a React component, or a small component that is not normally used on its own.

##### Component

A composition of Core Styles and Elements. Normally with some code that defines behavior. An example of a Component is a Dialog which is a composition of Typography and Buttons.

##### Feature

A Composition of Core Styles, Elements, and Components that defines a verticle slice of functionality. An example of a Feature is the Payment Method Row it combines Components, Elements, and Core Styles like Buttons, Action Menus, Icons, Typography, etc.
A Composition of Core Styles, Elements, and Components that defines a vertical slice of functionality. An example of a Feature is the Payment Method Row; it combines Components, Elements, and Core Styles like Buttons, Action Menus, Icons, Typography, etc.

#### Best Practices
Our stories are in the process of being updated to the latest Storybook 7.0 format.
We currently use MDX both for documentation and for defining stories in the same `.stories.mdx` file. However, Storybook has deprecated this functionality and they plan to remove it in a future version of Storybook.

As we begin to move away from the MDX format, please refer to Storybook's [documentation](https://storybook.js.org/docs/react/writing-docs/introduction) for how to write stories in the CSF format.
Please refer to Storybook's [documentation](https://storybook.js.org/docs/react/writing-docs/introduction) for how to write stories in the CSF format.
18 changes: 16 additions & 2 deletions docs/development-guide/10-local-dev-tools.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
# Local Dev Tools

To facilitate development and debugging, Cloud Manager includes a "Dev Tools" mode. Currently this mode is used for feature flag toggling, data mocking, and environment switching.
To facilitate development and debugging, Cloud Manager includes a "Dev Tools" mode. Currently this mode is used for feature flag toggling, data mocking, and theme & environment switching.

In order to access the dev tools, hover or click (mobile) on the 🛠 icon in the lower left corner of your browser window. The icon will be colored green if MSW is enabled.

This mode is enabled by default while running the development server. To disable it, add `?dev-tools=false` to the URL, or write `dev-tools: false` to local storage.

This mode is disabled by default in production builds, but can be enabled by adding `?dev-tools=true` to the URL, or `dev-tools: true` to local storage.
This mode is disabled by default in production builds.

## Feature Flags

The display of the Flags in dev tools is defined in the `options` array in `FeatureFlagTool.tsx`. While it is convenient to add those switches to the dev tools, it is not always necessary as they can clutter the UI. Additionally, it is important to clean them up once the feature has been battle tested in production.

The flags on/off values are stored in local storage for convenience and will be remembered on reload or app restart.

By default, the boolean flags checkboxes represent their true values as returned by Launch Darkly (dev environment). Hitting the reset button will bring them back to those default values and clear local storage.

## Theme Select

The theme select in dev tools is a convenient way to store the theme choice while MSW is enabled (it won't affect your actual Application settings/preferences). The default is "system".

## Writing a new tool

Expand Down
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"coverage": "yarn workspace linode-manager coverage",
"coverage:summary": "yarn workspace linode-manager coverage:summary",
"junit:summary": "ts-node scripts/junit-summary/index.ts",
"docs": "bunx vitepress@1.0.0-rc.35 dev docs"
"docs": "bunx vitepress@1.0.0-rc.44 dev docs"
},
"resolutions": {
"@babel/traverse": "^7.23.3",
Expand All @@ -58,11 +58,11 @@
"lodash": "^4.17.21",
"glob-parent": "^5.1.2",
"hosted-git-info": "^5.0.0",
"@types/react": "^17",
"yaml": "^2.3.0",
"word-wrap": "^1.2.4",
"semver": "^7.5.2",
"tough-cookie": "^4.1.3"
"tough-cookie": "^4.1.3",
"jackspeak": "2.1.1"
},
"workspaces": {
"packages": [
Expand Down
10 changes: 10 additions & 0 deletions packages/api-v4/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
## [2024-03-04] - v0.111.0

### Changed:

- Rename `database_scale` type to `database_resize` ([#10193](https://github.com/linode/manager/pull/10193))

### Upcoming Features:

- Accept placement group in Linode create payload ([#10195](https://github.com/linode/manager/pull/10195))

## [2024-02-20] - v0.110.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.110.0",
"version": "0.111.0",
"homepage": "https://github.com/linode/manager/tree/develop/packages/api-v4",
"bugs": {
"url": "https://github.com/linode/manager/issues"
Expand Down
2 changes: 1 addition & 1 deletion packages/api-v4/src/account/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ export type EventAction =
| 'community_question_reply'
| 'credit_card_updated'
| 'database_low_disk_space'
| 'database_scale'
| 'database_resize'
| 'database_backup_restore'
| 'database_create'
| 'database_credentials_reset'
Expand Down
22 changes: 17 additions & 5 deletions packages/api-v4/src/linodes/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { Region } from '../regions';
import type { IPAddress, IPRange } from '../networking/types';
import type { SSHKey } from '../profile/types';
import type { PlacementGroup } from '../placement-groups/types';
import type { PlacementGroupPayload } from '../placement-groups/types';

export type Hypervisor = 'kvm' | 'zen';

Expand All @@ -24,9 +24,7 @@ export interface Linode {
ipv4: string[];
ipv6: string | null;
label: string;
placement_groups:
| [Pick<PlacementGroup, 'id' | 'label' | 'affinity_type'>] // While the API returns an array of PlacementGroup objects for future proofing, we only support one PlacementGroup per Linode at this time, hence the tuple.
| [];
placement_group?: PlacementGroupPayload; // If not in a placement group, this will be excluded from the response.
type: string | null;
status: LinodeStatus;
updated: string;
Expand Down Expand Up @@ -230,10 +228,13 @@ export interface Kernel {
label: string;
version: string;
kvm: boolean;
xen: boolean;
architecture: KernelArchitecture;
pvops: boolean;
deprecated: boolean;
/**
* @example 2009-10-26T04:00:00
*/
built: string;
}

export interface NetStats {
Expand Down Expand Up @@ -338,6 +339,16 @@ export interface UserData {
user_data: string | null;
}

export interface CreateLinodePlacementGroupPayload {
id: number;
/**
* This parameter is silent in Cloud Manager, but still needs to be represented in the API types.
*
* @default false
*/
compliant_only?: boolean;
}

export interface CreateLinodeRequest {
type?: string;
region?: string;
Expand All @@ -357,6 +368,7 @@ export interface CreateLinodeRequest {
interfaces?: InterfacePayload[];
metadata?: UserData;
firewall_id?: number;
placement_group?: CreateLinodePlacementGroupPayload;
}

export type RescueRequestObject = Pick<
Expand Down
4 changes: 2 additions & 2 deletions packages/api-v4/src/placement-groups/placement-groups.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import type {
CreatePlacementGroupPayload,
PlacementGroup,
UnassignLinodesFromPlacementGroupPayload,
RenamePlacementGroupPayload,
UpdatePlacementGroupPayload,
} from './types';

/**
Expand Down Expand Up @@ -72,7 +72,7 @@ export const createPlacementGroup = (data: CreatePlacementGroupPayload) =>
*/
export const renamePlacementGroup = (
placementGroupId: number,
data: RenamePlacementGroupPayload
data: UpdatePlacementGroupPayload
) =>
Request<PlacementGroup>(
setURL(
Expand Down
Loading

0 comments on commit 9902757

Please sign in to comment.