Skip to content

Commit

Permalink
Merge branch 'main' into chore-sentence-case
Browse files Browse the repository at this point in the history
  • Loading branch information
JBR90 committed Nov 7, 2024
2 parents 051308c + 7a34686 commit 4abda5b
Show file tree
Hide file tree
Showing 26 changed files with 388 additions and 173 deletions.
60 changes: 60 additions & 0 deletions .github/workflows/chromatic.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: "Chromatic"

on: push

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-chromatic
cancel-in-progress: true

jobs:
changed-files:
runs-on: ubuntu-latest
name: changed-files
outputs:
all_changed_files: ${{ steps.changed-files.outputs.all_changed_files }}
any_changed: ${{ steps.changed-files.outputs.any_changed }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed files
id: changed-files
uses: tj-actions/changed-files@v44
with:
files: |
apps/nextjs/**
chromatic:
name: Run Chromatic
needs: [changed-files]
if: ${{ needs.changed-files.outputs.any_changed == 'true' }}

runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup pnpm
uses: pnpm/action-setup@v3
with:
version: 8
- uses: actions/setup-node@v4
with:
node-version: 20
cache: "pnpm"
- name: Install dependencies
run: pnpm install
- name: Inject Doppler env vars
uses: dopplerhq/[email protected]
id: doppler
with:
doppler-token: ${{ secrets.DOPPLER_TOKEN }}
inject-env-vars: true
- name: Run Chromatic
uses: chromaui/action@latest
with:
workingDir: apps/nextjs
exitZeroOnChanges: true
exitOnceUploaded: true
onlyChanged: true
30 changes: 30 additions & 0 deletions CHANGE_LOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,33 @@
## [1.14.1](https://github.com/oaknational/oak-ai-lesson-assistant/compare/v1.14.0...v1.14.1) (2024-11-07)


### Bug Fixes

* allow requests without a cookie header ([#352](https://github.com/oaknational/oak-ai-lesson-assistant/issues/352)) ([80f5050](https://github.com/oaknational/oak-ai-lesson-assistant/commit/80f50507ab370032a3ef6767bcfe5da0d8b6fe82))

# [1.14.0](https://github.com/oaknational/oak-ai-lesson-assistant/compare/v1.13.1...v1.14.0) (2024-11-07)


### Bug Fixes

* add missing dependencies to lesson plan tracking context ([#307](https://github.com/oaknational/oak-ai-lesson-assistant/issues/307)) ([3758dfc](https://github.com/oaknational/oak-ai-lesson-assistant/commit/3758dfcda8a937ca363c0eb40014b01d18c93c23))
* add missing prisma import ([#342](https://github.com/oaknational/oak-ai-lesson-assistant/issues/342)) ([a0ac1de](https://github.com/oaknational/oak-ai-lesson-assistant/commit/a0ac1de89dc6dda38ab64a02054e992072332fd5))
* disable feature flagg polling in tests ([c44e1f1](https://github.com/oaknational/oak-ai-lesson-assistant/commit/c44e1f10e98dcda37367f2cd03b324078c7b910f))
* null render in sidebar provider ([#337](https://github.com/oaknational/oak-ai-lesson-assistant/issues/337)) ([9a12851](https://github.com/oaknational/oak-ai-lesson-assistant/commit/9a12851471aeb5f36e7aebd9c1652d0c2a565966))
* remaining linting fixes ([#272](https://github.com/oaknational/oak-ai-lesson-assistant/issues/272)) ([18a0f70](https://github.com/oaknational/oak-ai-lesson-assistant/commit/18a0f7061bc9d8bd72c4f6d44eec003acd878df1))
* set up server side styled-components ([f221c24](https://github.com/oaknational/oak-ai-lesson-assistant/commit/f221c2442617031fa694708da953b4a5f1ea5e6c))
* skip instrumentation when running turbopack - fix HMR ([4d6fd3b](https://github.com/oaknational/oak-ai-lesson-assistant/commit/4d6fd3b963710703b547cda5b2085bfc7f00f941))


### Features

* add rag schema (migration) ([#343](https://github.com/oaknational/oak-ai-lesson-assistant/issues/343)) ([638f43f](https://github.com/oaknational/oak-ai-lesson-assistant/commit/638f43fa0167f28974250f3da2d67ef95aaae57e))
* allow us to configure the server port for local testing ([#308](https://github.com/oaknational/oak-ai-lesson-assistant/issues/308)) ([33bee19](https://github.com/oaknational/oak-ai-lesson-assistant/commit/33bee19e5e631428b648159452ef5af5dbec36bd))
* bootstrap posthog feature flags with local evaluation ([15e8a67](https://github.com/oaknational/oak-ai-lesson-assistant/commit/15e8a67e9a1ce8e08baa5642c7fffbd2193d3b64))
* sync featureFlagGroup from clerk to posthog ([46b4f13](https://github.com/oaknational/oak-ai-lesson-assistant/commit/46b4f13a1e887177035a9d195886f34647a87ac9))
* update emails to use html ([#319](https://github.com/oaknational/oak-ai-lesson-assistant/issues/319)) ([a71e7bc](https://github.com/oaknational/oak-ai-lesson-assistant/commit/a71e7bc4b6416ef01b48de4c950805f8244e658b))
* use featureFlagGroup claim for feature flags ([759534a](https://github.com/oaknational/oak-ai-lesson-assistant/commit/759534a8b8189c25d665b34db1cdf7f0b7a8f31e))

## [1.13.1](https://github.com/oaknational/oak-ai-lesson-assistant/compare/v1.13.0...v1.13.1) (2024-11-05)


Expand Down
3 changes: 2 additions & 1 deletion apps/nextjs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ tests-e2e/.auth
.env.sentry-build-plugin

*storybook.log
.chromatic.log

# Playwright artifacts
playwright-report
playwright-report
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import React from "react";
import { Theme } from "@radix-ui/themes";
import "@radix-ui/themes/styles.css";

export const ThemeDecorator = (Story: React.ComponentType) => (
export const RadixThemeDecorator = (Story: React.ComponentType) => (
<Theme>
<Story />
</Theme>
Expand Down
56 changes: 22 additions & 34 deletions apps/nextjs/.storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,10 @@ import "@fontsource/lexend/900.css";
import { OakThemeProvider, oakDefaultTheme } from "@oaknational/oak-components";
import type { Preview, Decorator } from "@storybook/react";

// ModerationProvider is coming in the main Chat.tsx refactor
//import { ModerationProvider } from "../src/components/AppComponents/Chat/Chat/ModerationProvider";
import { TooltipProvider } from "../src/components/AppComponents/Chat/ui/tooltip";
import { DialogProvider } from "../src/components/AppComponents/DialogContext";
import { CookieConsentProvider } from "../src/components/ContextProviders/CookieConsentProvider";
import { DemoProvider } from "../src/components/ContextProviders/Demo";
import LessonPlanTrackingProvider from "../src/lib/analytics/lessonPlanTrackingContext";
import { SidebarProvider } from "../src/lib/hooks/use-sidebar";
import { AnalyticsProvider } from "../src/mocks/analytics/provider";
import { TRPCReactProvider } from "../src/utils/trpc";
import { MockClerkProvider } from "./MockClerkProvider";
import { ThemeDecorator } from "./ThemeDecorator";
import { RadixThemeDecorator } from "./decorators/RadixThemeDecorator";
import "./preview.css";

const preview: Preview = {
Expand All @@ -35,33 +27,29 @@ const preview: Preview = {
tags: ["autodocs"],
};

// Providers not currently used
// - MockClerkProvider
// - CookieConsentProvider
// - DemoProvider
// - LessonPlanTrackingProvider
// - DialogProvider
// - OakThemeProvider
// - SidebarProvider
// - ChatModerationProvider

export const decorators: Decorator[] = [
ThemeDecorator,
RadixThemeDecorator,
(Story) => (
<MockClerkProvider>
<CookieConsentProvider>
{" "}
<TRPCReactProvider>
<DemoProvider>
<AnalyticsProvider>
<LessonPlanTrackingProvider chatId={"faked"}>
<DialogProvider>
<OakThemeProvider theme={oakDefaultTheme}>
<SidebarProvider>
<TooltipProvider>
{/* <ModerationProvider initialModerations={[]}> */}
<Story />
{/* </ModerationProvider> */}
</TooltipProvider>
</SidebarProvider>
</OakThemeProvider>
</DialogProvider>
</LessonPlanTrackingProvider>
</AnalyticsProvider>
</DemoProvider>{" "}
</TRPCReactProvider>
</CookieConsentProvider>
</MockClerkProvider>
<>
{/* TODO: Mock tRPC calls with MSW */}
<TRPCReactProvider>
<AnalyticsProvider>
<TooltipProvider>
<Story />
</TooltipProvider>
</AnalyticsProvider>
</TRPCReactProvider>
</>
),
];

Expand Down
6 changes: 6 additions & 0 deletions apps/nextjs/chromatic.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"onlyChanged": true,
"projectId": "Project:672908473f629875f0be294f",
"storybookBaseDir": "apps/nextjs",
"zip": true
}
3 changes: 2 additions & 1 deletion apps/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"with-env": "dotenv -e ../../.env --",
"aila": "tsx scripts/aila-cli.ts",
"storybook": "dotenv -e ../../.env -- storybook dev -p 6006 --no-open",
"build-storybook": "dotenv -e ../../.env -- storybook build"
"build-storybook": "dotenv -e ../../.env -- storybook build",
"chromatic": "pnpm with-env pnpm dlx chromatic"
},
"prettier": "@oakai/prettier-config",
"dependencies": {
Expand Down
2 changes: 1 addition & 1 deletion apps/nextjs/src/app/api/aila-download-all/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ async function getHandler(req: Request): Promise<Response> {
}

const lessonExport = await prisma.lessonExport.findFirst({
where: { gdriveFileId: fileId, userId },
where: { gdriveFileId: fileId, userId, expiredAt: null },
});

if (!lessonExport) {
Expand Down
1 change: 1 addition & 0 deletions apps/nextjs/src/app/api/aila-download/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ async function getHandler(req: Request): Promise<Response> {
where: {
gdriveFileId: fileId,
userId,
expiredAt: null,
},
cacheStrategy: { ttl: 60 * 5, swr: 60 * 2 },
});
Expand Down
140 changes: 140 additions & 0 deletions apps/nextjs/src/app/api/cron-jobs/expired-exports/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { prisma } from "@oakai/db";
import { googleDrive } from "@oakai/exports/src/gSuite/drive/client";
import { aiLogger } from "@oakai/logger";
import * as Sentry from "@sentry/node";
import type { NextRequest } from "next/server";
import { isTruthy } from "remeda";

const log = aiLogger("cron");

const requiredEnvVars = ["CRON_SECRET", "GOOGLE_DRIVE_OUTPUT_FOLDER_ID"];

requiredEnvVars.forEach((envVar) => {
if (!process.env[envVar]) {
throw new Error(`Environment variable ${envVar} is not set.`);
}
});

async function updateExpiredAt(fileIds: string[]) {
if (fileIds.length === 0) {
log.info("No file IDs to update.");
return;
}

try {
const result = await prisma.lessonExport.updateMany({
where: {
gdriveFileId: {
in: fileIds,
},
},
data: {
expiredAt: new Date(),
},
});
log.info(`Updated expiredAt for ${fileIds.length} files.`);

if (result.count === fileIds.length) {
log.info("All files updated successfully.");
} else {
throw new Error(
`Expected to update ${fileIds.length} files, but only updated ${result.count}.`,
);
}
} catch (error) {
log.error("Error updating expiredAt field in the database:", error);
throw error;
}
}

async function deleteExpiredExports(fileIds: string[]) {
try {
for (const id of fileIds) {
await googleDrive.files.delete({ fileId: id });
log.info("Deleted:", id);
}
} catch (error) {
log.error("Error deleting old files from folder:", error);
throw error;
}
}

interface FetchExpiredExportsOptions {
folderId: string;
daysAgo: number;
}

async function fetchExpiredExports({
folderId,
daysAgo,
}: FetchExpiredExportsOptions) {
try {
const currentDate = new Date();
const targetDate = new Date(
currentDate.setDate(currentDate.getDate() - daysAgo),
).toISOString();

const query = `modifiedTime < '${targetDate}' and '${folderId}' in parents`;

const res = await googleDrive.files.list({
q: query,
fields: "files(id, name, modifiedTime, ownedByMe )",
pageSize: 1000,
});

const files =
res.data.files?.filter((file) => file.ownedByMe === true) || [];

if (files.length === 0) {
log.info(
"No files found that are older than one month in the specified folder.",
);
return null;
}

log.info(`Found ${files.length} files older than one month in folder:`);
return files;
} catch (error) {
log.error("Error fetching old files from folder:", error);
return null;
}
}

export async function GET(request: NextRequest) {
try {
const authHeader = request.headers.get("authorization");

const cronSecret = process.env.CRON_SECRET;
const folderId = process.env.GOOGLE_DRIVE_OUTPUT_FOLDER_ID;

if (!cronSecret) {
log.error("Missing cron secret");
return new Response("Missing cron secret", { status: 500 });
}
if (!folderId) {
log.error("No folder ID provided.");
return new Response("No folder ID provided", { status: 500 });
}

if (authHeader !== `Bearer ${cronSecret}`) {
log.error("Authorization failed. Invalid token.");
return new Response("Unauthorized", { status: 401 });
}

const files = await fetchExpiredExports({ folderId, daysAgo: 14 });

if (!files || files.length === 0) {
return new Response("No expired files found", { status: 404 });
}

const validFileIds = files.map((file) => file.id).filter(isTruthy);

await updateExpiredAt(validFileIds);
await deleteExpiredExports(validFileIds);
} catch (error) {
Sentry.captureException(error);
return new Response("Internal Server Error", { status: 500 });
}

return new Response(JSON.stringify({ success: true }), { status: 200 });
}

This file was deleted.

Loading

0 comments on commit 4abda5b

Please sign in to comment.