Skip to content

Commit eed4a4e

Browse files
committed
fix tests, better docker
1 parent dbe9a34 commit eed4a4e

32 files changed

Lines changed: 543 additions & 2439 deletions

Dockerfile

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,15 @@
11
# Stage 1: Dependencies
2-
FROM node:20-alpine AS deps
2+
FROM node:22-alpine AS deps
33
WORKDIR /app
44

55
# Install dependencies based on the preferred package manager
66
COPY package.json package-lock.json* ./
77
RUN npm ci --only=production && npm cache clean --force
88

99
# Stage 2: Build
10-
FROM node:20-alpine AS builder
10+
FROM node:22-alpine AS builder
1111
WORKDIR /app
1212

13-
# Declare build arguments for environment variables
14-
ARG DISCORD_BOT_TOKEN
15-
ARG LUMA_API_KEY
16-
ARG STRIPE_SECRET_KEY
17-
ARG ETHERSCAN_API_KEY
18-
ARG MONERIUM_CLIENT_ID
19-
ARG MONERIUM_CLIENT_SECRET
20-
ARG RESEND_API_KEY
21-
22-
# Set environment variables from build args
23-
ENV DISCORD_BOT_TOKEN=$DISCORD_BOT_TOKEN
24-
ENV LUMA_API_KEY=$LUMA_API_KEY
25-
ENV STRIPE_SECRET_KEY=$STRIPE_SECRET_KEY
26-
ENV ETHERSCAN_API_KEY=$ETHERSCAN_API_KEY
27-
ENV MONERIUM_CLIENT_ID=$MONERIUM_CLIENT_ID
28-
ENV MONERIUM_CLIENT_SECRET=$MONERIUM_CLIENT_SECRET
29-
ENV RESEND_API_KEY=$RESEND_API_KEY
30-
3113
# Copy dependencies from deps stage
3214
COPY --from=deps /app/node_modules ./node_modules
3315
COPY . .
@@ -42,7 +24,7 @@ ENV NEXT_TELEMETRY_DISABLED=1
4224
RUN npm run build
4325

4426
# Stage 3: Production runner
45-
FROM node:20-alpine AS runner
27+
FROM node:22-alpine AS runner
4628
WORKDIR /app
4729

4830
ENV NODE_ENV=production
@@ -55,11 +37,18 @@ RUN adduser --system --uid 1001 nextjs
5537
# Copy necessary files
5638
COPY --from=builder /app/public ./public
5739
COPY --from=builder /app/package.json ./package.json
40+
COPY --from=builder /app/package-lock.json ./package-lock.json
5841

5942
# Copy built application
6043
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
6144
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
6245

46+
# Copy scripts and node_modules for data fetching
47+
COPY --from=builder --chown=nextjs:nodejs /app/scripts ./scripts
48+
COPY --from=builder --chown=nextjs:nodejs /app/src ./src
49+
COPY --from=builder --chown=nextjs:nodejs /app/node_modules ./node_modules
50+
COPY --from=builder --chown=nextjs:nodejs /app/tsconfig.json ./tsconfig.json
51+
6352
# Create data directory with proper permissions
6453
RUN mkdir -p /app/data && chown nextjs:nodejs /app/data
6554

jest.config.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ const createJestConfig = nextJest({
77
const customJestConfig = {
88
setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
99
testMatch: ["<rootDir>/tests/**/*.test.ts", "<rootDir>/tests/**/*.test.tsx"],
10+
testPathIgnorePatterns: ["/node_modules/", "/tests/e2e/"],
1011
moduleNameMapper: {
1112
"^@/(.*)$": "<rootDir>/src/$1",
1213
},
1314
transformIgnorePatterns: [
1415
"node_modules/(?!(next-auth)/)",
1516
],
16-
testEnvironment: "node", // Default to node for API tests
17+
// Default to node environment for server-side tests
18+
// React component tests (.tsx) should add @jest-environment jsdom at the top
19+
testEnvironment: "node",
1720
testEnvironmentOptions: {
1821
customExportConditions: ["node"],
1922
},

scripts/generate-events.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ function loadLumaEvents(year: string, month: string): Map<string, LumaEvent> {
224224
DATA_DIR,
225225
year,
226226
month,
227+
"calendars",
227228
"luma",
228229
`${calendarId}.json`
229230
);

src/app/api/booking-request/route.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import { NextResponse } from "next/server"
33
import { createDiscordThread } from "@/lib/discord"
44
import settings from "@/settings/settings.json"
55

6-
const resend = new Resend(process.env.RESEND_API_KEY)
7-
86
const roomNames: Record<string, string> = {
97
mush: "Mush Room",
108
angel: "Angel Room",
@@ -14,6 +12,9 @@ const roomNames: Record<string, string> = {
1412

1513
export async function POST(request: Request) {
1614
try {
15+
// Initialize Resend client at runtime, not at build time
16+
const resend = new Resend(process.env.RESEND_API_KEY)
17+
1718
const data = await request.json()
1819

1920
const {

src/app/api/contact/route.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@ import { NextResponse } from "next/server"
33
import { createDiscordThread } from "@/lib/discord"
44
import settings from "@/settings/settings.json"
55

6-
const resend = new Resend(process.env.RESEND_API_KEY)
7-
86
const reasonLabels: Record<string, string> = {
97
"booking-room": "Booking a room",
108
"joining-community": "Joining the community",
@@ -16,6 +14,9 @@ const reasonLabels: Record<string, string> = {
1614

1715
export async function POST(request: Request) {
1816
try {
17+
// Initialize Resend client at runtime, not at build time
18+
const resend = new Resend(process.env.RESEND_API_KEY)
19+
1920
const data = await request.json()
2021

2122
const { name, email, organisation, reason, message } = data

src/app/api/membership-application/route.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import { Resend } from "resend"
33
import { createDiscordThread } from "@/lib/discord"
44
import settings from "@/settings/settings.json"
55

6-
const resend = new Resend(process.env.RESEND_API_KEY)
7-
86
export async function POST(request: Request) {
97
try {
8+
// Initialize Resend client at runtime, not at build time
9+
const resend = new Resend(process.env.RESEND_API_KEY)
10+
1011
const { name, organisation, email, plan, motivation } = await request.json()
1112

1213
if (!name || !email || !plan || !motivation) {

src/app/api/workshop-booking/route.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ import { NextResponse } from "next/server"
33
import { createDiscordThread } from "@/lib/discord"
44
import settings from "@/settings/settings.json"
55

6-
const resend = new Resend(process.env.RESEND_API_KEY)
7-
86
export async function POST(request: Request) {
97
try {
8+
// Initialize Resend client at runtime, not at build time
9+
const resend = new Resend(process.env.RESEND_API_KEY)
10+
1011
const body = await request.json()
1112
const { name, organisation, numberOfPeople, date, time, place, comment, workshop, email } = body
1213

src/auth.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import Discord from "next-auth/providers/discord"
33
import settings from "@/settings/settings.json"
44

55
export const { handlers, signIn, signOut, auth } = NextAuth({
6+
basePath: "/api/auth",
7+
trustHost: true,
68
providers: [
79
Discord({
810
clientId: process.env.AUTH_DISCORD_ID!,

src/lib/services/notifications.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import { Resend } from "resend"
77
import settings from "@/settings/settings.json"
88
import { createThread, sendMessage, isDiscordConfigured } from "@/lib/discord"
99

10-
const resend = new Resend(process.env.RESEND_API_KEY)
10+
const RESEND_API_KEY = process.env.RESEND_API_KEY;
11+
const resend = RESEND_API_KEY ? new Resend(RESEND_API_KEY) : null;
1112

1213
export interface EmailOptions {
1314
to: string
@@ -25,10 +26,21 @@ export interface DiscordThreadOptions {
2526

2627
/**
2728
* Send an email using Resend
29+
* If RESEND_API_KEY is not set, logs a warning instead
2830
*/
2931
export async function sendEmail(options: EmailOptions) {
3032
const { to, subject, html, cc, replyTo } = options
3133

34+
if (!resend) {
35+
console.warn(`⚠️ Email not sent (RESEND_API_KEY not set): ${subject}`);
36+
console.log(` To: ${to}`);
37+
console.log(` Subject: ${subject}`);
38+
return {
39+
id: 'mock-email-id',
40+
error: null,
41+
};
42+
}
43+
3244
return resend.emails.send({
3345
from: `Commons Hub <${settings.email.from}>`,
3446
to,

src/types/contributors.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Contributors data types
3+
* Generated from data/{year}/{month}/contributors.json
4+
*/
5+
6+
export interface ContributorProfile {
7+
name: string;
8+
username: string;
9+
description: string | null;
10+
avatar_url: string;
11+
roles: string[];
12+
}
13+
14+
export interface ContributorTokens {
15+
in: number;
16+
out: number;
17+
}
18+
19+
export interface ContributorDiscord {
20+
messages: number;
21+
mentions: number;
22+
}
23+
24+
export interface Contributor {
25+
id: string;
26+
profile: ContributorProfile;
27+
tokens: ContributorTokens;
28+
discord: ContributorDiscord;
29+
address: string;
30+
}
31+
32+
export interface ContributorsSummary {
33+
totalContributors: number;
34+
contributorsWithAddress: number;
35+
contributorsWithTokens: number;
36+
totalTokensIn: number;
37+
totalTokensOut: number;
38+
totalMessages: number;
39+
}
40+
41+
export interface ContributorsFile {
42+
year: string;
43+
month: string;
44+
summary: ContributorsSummary;
45+
contributors: Contributor[];
46+
}

0 commit comments

Comments
 (0)