Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

build: release candidate #449

Merged
merged 16 commits into from
Dec 16, 2024
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
407 changes: 407 additions & 0 deletions .dependency-cruiser.cjs

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,6 @@ yarn-error.log*
.vscode/*.settings.json

.sonar
.sonar/**/*
.sonar/**/*

dependency-graph.svg
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"bradlc.vscode-tailwindcss",
"Prisma.prisma",
"orta.vscode-jest",
"ms-playwright.playwright"
"ms-playwright.playwright",
"sonarsource.sonarlint-vscode"
]
}
72 changes: 72 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ Oak AI Lesson Assistant is a project focused on experimenting with AI models and
- [End-to-end tests](#end-to-end-tests)
- [Playwright tags](#playwright-tags)
- [Testing in VSCode](#testing-in-vscode)
- [Standards](#standards)
- [Typescript](#typescript)
- [ES Modules](#esmodules)
- [CommonJS](#commonjs)
- [Code quality](#quality)
- [Sonar](#sonar)
- [ESLint](#eslint)
- [Prettier](#prettier)
- [Tsconfig]("#tsconfig)
- [Dependency cruiser](#dependency-cruiser)
- [Release process](#release-process)
- [PNPM / dependency problems](#pnpm--dependency-problems)
- [External contributions](#external-contributions)
Expand Down Expand Up @@ -176,6 +186,68 @@ Our Playwright tests are organised with tags:

Install the Jest and Playwright extensions recommended in the workspace config. Testing icons should appear in the gutter to the left of each test when viewing a test file. Clicking the icon will run the test. The testing tab in the VSCode nav bar provides an overview.

## Standards

### Typescript

By default, we develop in Typescript and aim to be up to date with the latest version. New code should default to being written in Typescript unless it is not possible.

### ES Modules

All packages are configured to be ES Modules.

### CommonJS

Currently NextJS, Tailwind and some other tools has some code which needs to be CommonJS. For these files, you should use the .cjs extension so that the correct linting rules are applied.

## Code quality

We use several tools to ensure code quality in the codebase and for checks during development. These checks run on each PR in Github to ensure we maintain good code quality. You can also run many of these checks locally before making a PR.

### Sonar

If you are using VS Code or Cursor, consider installing the SonarQube for IDE extension. This will give you feedback while you were as to any code quality or security issues that it has detected.

If you would like to run a Sonar scan locally, use the following command:

```shell
pnpm sonar
```

You will need to log in to Sonar when prompted the first time. This will generate a full report for you of your local development environment. Usually it is easier to make a PR and have this run for you automatically.

### ESLint

We have a single ESLint config for the whole monorepo. You will find it in packages/eslint-config.

This is using the latest version of ESLint and you should note that the config file format has changed to the "Flat file" config in version 9.

Each package does not have its own ESLint config by default. Instead we have a single config file, with regex path matchers to turn on/off rules that are specific for each package. This can be overridden and you can see an example of that in the logger package.

Each package specifies in its package.json file that it should use this shared config and there is a root ESLint config file for the whole mono repo which specifies that it should do the same.

To check for linting errors, run the following command:

```shell
pnpm lint
```

If you want to check for linting errors in an individual package, cd into that package and run the same command.

### Prettier

We also have a single Prettier config, which is located in packages/prettier-config. In general there should be no need to change this on a per-package basis.

### Tsconfig

We have an overall tsconfig.json file which specifies the overall Typescript configuration for the project. Then each package extends from it.

You can check the codebase for any Typescript issues by running the following command:

```shell
pnpm type-check
```

## Release process

The current release process is fully documented [in Notion](https://www.notion.so/oaknationalacademy/Branch-Strategy-and-Release-Process-ceeb32937af0426ba495565288e18844?pvs=4), but broadly works as follows:
Expand Down
91 changes: 91 additions & 0 deletions apps/nextjs/.storybook/chromatic.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import "@storybook/csf";

type ChromaticModes = "mobile" | "mobile-wide" | "desktop" | "desktop-wide";

export function chromaticParams(modes: ChromaticModes[]) {
return {
chromatic: {
modes: {
...(modes.includes("mobile") && {
mobile: { viewport: "mobile" },
}),
...(modes.includes("mobile-wide") && {
mobile: { viewport: "mobile-wide" },
}),
...(modes.includes("desktop") && {
desktop: { viewport: "desktop" },
}),
...(modes.includes("desktop-wide") && {
"desktop-wide": { viewport: "desktopWide" },
}),
},
},
};
}

declare module "@storybook/csf" {
interface Parameters {
/**
* Parameters for chromatic
*/
chromatic?: {
/**
* Delay capture for a fixed time (in milliseconds) to allow your story to get into
* the intended state
*
* @see [delaying snapshots chromatic documentation](https://www.chromatic.com/docs/delay)
*/
delay?: number;
/**
* Override this behavior in instances where a single pixel change is not flagged by
* Chromatic but should be
*
* * @see [anti-aliasing chromatic documentation](https://www.chromatic.com/docs/threshold#anti-aliasing)
*
* @default false
*/
diffIncludeAntiAliasing?: boolean;
/**
* The diffThreshold parameter allows you to fine tune the threshold for visual change
* between snapshots before they're flagged by Chromatic. Sometimes you need assurance
* to the sub-pixel and other times you want to skip visual noise generated by
* non-deterministic rendering such as anti-aliasing.
*
* 0 is the most accurate. 1 is the least accurate.
*
* @default 0.063
*/
diffThreshold?: number;
/**
* You can omit stories entirely from Chromatic testing using the disable story parameter.
*
* @see [ignoring elements chromatic documentation](https://www.chromatic.com/docs/ignoring-elements)
*/
disable?: boolean;
/**
* Modes
*
* @see [modes chromatic documentation](https://www.chromatic.com/docs/modes)
*/
modes?: Record<
string,
{
viewport?: string | number;
theme?: "light" | "dark";
backgrounds?: { value: string };
}
>;
/**
* Define one or more viewport sizes to capture. Note, units are considered in pixels
*/
viewports?: number[];
/**
* To specify that Chromatic should pause the animation at the end instead of reseting
* them to their beginning state.
*
* @see [animations chromatic documentation](https://www.chromatic.com/docs/animations)
*/
pauseAnimationAtEnd?: boolean;
};
}
}
35 changes: 35 additions & 0 deletions apps/nextjs/.storybook/decorators/AnalyticsDecorator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import React from "react";

import type { Decorator } from "@storybook/react";
import { fn } from "@storybook/test";

import {
analyticsContext,
type AnalyticsContext,
} from "../../src/components/ContextProviders/AnalyticsProvider";

declare module "@storybook/csf" {
interface Parameters {
analyticsContext?: Partial<AnalyticsContext>;
}
}

export const AnalyticsDecorator: Decorator = (Story, { parameters }) => {
return (
<analyticsContext.Provider
value={
{
track: fn(),
trackEvent: fn(),
identify: fn(),
reset: fn(),
page: fn(),
posthogAiBetaClient: {},
...parameters.analyticsContext,
} as unknown as AnalyticsContext
}
>
<Story />
</analyticsContext.Provider>
);
};
20 changes: 20 additions & 0 deletions apps/nextjs/.storybook/decorators/ChatDecorator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";

import type { Decorator } from "@storybook/react";

import {
ChatContext,
type ChatContextProps,
} from "../../src/components/ContextProviders/ChatProvider";

declare module "@storybook/csf" {
interface Parameters {
chatContext?: Partial<ChatContextProps>;
}
}

export const ChatDecorator: Decorator = (Story, { parameters }) => (
<ChatContext.Provider value={parameters.chatContext as ChatContextProps}>
<Story />
</ChatContext.Provider>
);
62 changes: 62 additions & 0 deletions apps/nextjs/.storybook/decorators/DemoDecorator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React from "react";

import type { Decorator } from "@storybook/react";
import invariant from "tiny-invariant";

import {
DemoContext,
type DemoContextProps,
} from "@/components/ContextProviders/Demo";

declare module "@storybook/csf" {
interface Parameters {
demoContext?: DemoContextProps;
}
}

export const DemoDecorator: Decorator = (Story, { parameters }) => {
const value = parameters.demoContext;
invariant(
value,
"DemoDecorator requires a DemoContext. Please call ...demoParams() in the parameters",
);

return (
<DemoContext.Provider value={value}>
<Story />
</DemoContext.Provider>
);
};

const demoBase: DemoContextProps["demo"] = {
appSessionsRemaining: 2,
appSessionsPerMonth: 3,
contactHref: "https://share.hsforms.com/1R9ulYSNPQgqElEHde3KdhAbvumd",
};

type DemoParams = {
isDemoUser: boolean;
demo?: Partial<DemoContextProps["demo"]>;
isSharingEnabled?: boolean;
};
export const demoParams = (
args: DemoParams,
): { demoContext: DemoContextProps } => {
const isSharingEnabled = args.isSharingEnabled ?? true;

const context: DemoContextProps = args.isDemoUser
? {
isDemoUser: true,
demo: { ...demoBase, ...args.demo },
isSharingEnabled,
}
: {
isDemoUser: false,
demo: undefined,
isSharingEnabled,
};

return {
demoContext: context,
};
};
30 changes: 30 additions & 0 deletions apps/nextjs/.storybook/decorators/DialogContentDecorator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from "react";

import type { Decorator } from "@storybook/react";
import { fn } from "@storybook/test";

import type { DialogTypes } from "../../src/components/AppComponents/Chat/Chat/types";
import { DialogContext } from "../../src/components/AppComponents/DialogContext";

declare module "@storybook/csf" {
interface Parameters {
dialogWindow?: DialogTypes;
}
}

export const DialogContentDecorator: Decorator = (Story, { parameters }) => {
return (
<DialogContext.Provider
value={{
dialogWindow: parameters.dialogWindow ?? "",
setDialogWindow: fn(),
dialogProps: {},
setDialogProps: fn(),
openSidebar: false,
setOpenSidebar: fn(),
}}
>
<Story />
</DialogContext.Provider>
);
};
21 changes: 21 additions & 0 deletions apps/nextjs/.storybook/decorators/LessonPlanTrackingDecorator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from "react";

import type { Decorator } from "@storybook/react";
import { fn } from "@storybook/test";

import { LessonPlanTrackingContext } from "../../src/lib/analytics/lessonPlanTrackingContext";

export const LessonPlanTrackingDecorator: Decorator = (Story) => (
<LessonPlanTrackingContext.Provider
value={{
onClickContinue: fn(),
onClickRetry: fn(),
onClickStartFromExample: fn(),
onClickStartFromFreeText: fn(),
onStreamFinished: fn(),
onSubmitText: fn(),
}}
>
<Story />
</LessonPlanTrackingContext.Provider>
);
3 changes: 2 additions & 1 deletion apps/nextjs/.storybook/decorators/RadixThemeDecorator.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import React from "react";

import { Theme } from "@radix-ui/themes";
import { Decorator } from "@storybook/react";

export const RadixThemeDecorator = (Story: React.ComponentType) => (
export const RadixThemeDecorator: Decorator = (Story) => (
<Theme>
<Story />
</Theme>
Expand Down
Loading
Loading