Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
028d46c
feat: Setup GitHub Actions Workflow
od-hunter Mar 21, 2025
92790c6
feat: Setup GitHub Actions Workflow
od-hunter Mar 21, 2025
3a689c4
feat: config setup for the testing environment
od-hunter Mar 22, 2025
529f7d2
feat: Jest config file for testing
od-hunter Mar 22, 2025
6adebd2
feat: docker file for local development
od-hunter Mar 22, 2025
32329f4
feat: Docker file for containerization
od-hunter Mar 22, 2025
96b0d8c
Merge branch 'develop' into CI/CD-Implementation
od-hunter Mar 26, 2025
7cf88e0
feat: implememnt `Light/Dark` with `next/theme` over custom
Mar 28, 2025
1f84098
...
Mar 28, 2025
901e59f
Merge pull request #190 from Jemiiah/feat/theme
JosueBrenes Mar 30, 2025
b08ab7d
Merge branch 'develop' into CI/CD-Implementation
od-hunter Mar 31, 2025
2c9cc88
fix: enhance the Github Actions workflow with better improvements
od-hunter Mar 31, 2025
2582eb4
Merge branch 'CI/CD-Implementation' of https://github.com/od-hunter/f…
od-hunter Mar 31, 2025
81a3179
add packages
od-hunter Apr 13, 2025
f1ab52d
add sample test
od-hunter Apr 13, 2025
9eeaade
fix theme
od-hunter Apr 13, 2025
d48f8cd
fix linting errors
od-hunter Apr 13, 2025
ff5a2a4
fix type checks
od-hunter Apr 13, 2025
e54ba88
fix cypress test
od-hunter Apr 13, 2025
37d23f6
fix cypress
od-hunter Apr 13, 2025
3698fcd
remove unused solana package
od-hunter Apr 13, 2025
455099f
fix npm error
od-hunter Apr 13, 2025
b38ec25
fix audit
od-hunter Apr 13, 2025
1fefebe
fix lighthouse naming
od-hunter Apr 13, 2025
7f889d7
fix ci
od-hunter Apr 13, 2025
2b46dd1
add setup guid
od-hunter Apr 13, 2025
1a7ed9b
use v4
od-hunter Apr 13, 2025
2328dbc
cache npm modules
od-hunter Apr 14, 2025
99598ad
fix target version
od-hunter Apr 14, 2025
38b2cfc
remove linting from workflow
od-hunter May 1, 2025
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
95 changes: 95 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
name: Next.js CI/CD Pipeline

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
build-and-test:
runs-on: ubuntu-latest

strategy:
matrix:
node-version: [18.x] # Compatible with React 19 and Next.js 15

steps:
- uses: actions/checkout@v3

- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: "npm"

- name: Install dependencies
run: npm ci

- name: Lint
# Using the ESLint configuration from eslint.config.mjs
run: npm run lint

- name: Type check
run: npm run type-check

- name: Test
run: npm run test

- name: Build
run: npm run build
env:
# Set environment variables based on the environment
NODE_ENV: production
# Add other environment variables as needed, using secrets
API_URL: ${{ secrets.API_URL }}

- name: Security audit
run: npm audit --production

- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: build-output
path: .next/
retention-days: 7

deploy-dev:
needs: build-and-test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3

- name: Download build artifacts
uses: actions/download-artifact@v3
with:
name: build-output
path: .next/

- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "18.x"

- name: Install dependencies
run: npm ci

- name: Deploy to Dev Environment (Vercel)
uses: amondnet/vercel-action@v20
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
vercel-args: "--prod"
working-directory: ./

- name: Notify Deployment
uses: rtCamp/action-slack-notify@v2
env:
SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
SLACK_CHANNEL: ci-cd-notifications
SLACK_TITLE: Dev Deployment Completed
SLACK_MESSAGE: "Next.js application successfully deployed to development environment"
SLACK_COLOR: good
58 changes: 58 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Stage 1: Dependencies
FROM node:18-alpine AS deps
WORKDIR /app

# Copy package files and install dependencies
COPY package.json package-lock.json ./
COPY tsconfig.json ./
COPY next.config.ts ./
COPY eslint.config.mjs ./
COPY postcss.config.mjs ./
COPY tailwind.config.ts ./
RUN npm ci

# Stage 2: Builder
FROM node:18-alpine AS builder
WORKDIR /app

# Copy dependencies
COPY --from=deps /app/node_modules ./node_modules
COPY . .

# Set environment variables for build
ARG NODE_ENV=production
ENV NODE_ENV=${NODE_ENV}

# Build application
RUN npm run build

# Stage 3: Runner
FROM node:18-alpine AS runner
WORKDIR /app

# Set to production environment
ENV NODE_ENV production

# Add non-root user for security
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
RUN mkdir .next
RUN chown nextjs:nodejs .next

# Copy only necessary files from builder
COPY --from=builder --chown=nextjs:nodejs /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
COPY --from=builder /app/next.config.js ./

# Switch to non-root user
USER nextjs

# Expose port
EXPOSE 3000

# Set hostname to listen on all interfaces
ENV HOSTNAME "0.0.0.0"

# Start the application
CMD ["node", "server.js"]
22 changes: 22 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
version: "3"

services:
nextjs-app:
build:
context: .
dockerfile: Dockerfile
target: builder
command: npm run dev
ports:
- "3000:3000"
volumes:
- .:/app
- /app/node_modules
- /app/.next
environment:
- NODE_ENV=development
- NEXT_PUBLIC_API_URL=http://localhost:3000/api
# Add any other services your app depends on (e.g., mock API server, database)
# For example:
# depends_on:
# - api-mock
35 changes: 35 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
module.exports = {
testEnvironment: "jsdom",
collectCoverageFrom: [
"src/**/*.{ts,tsx,js,jsx}",
"!src/**/*.d.ts",
"!src/**/*.stories.{ts,tsx}",
"!**/node_modules/**",
],
coverageThreshold: {
global: {
statements: 70,
branches: 70,
functions: 70,
lines: 70,
},
},
moduleNameMapper: {
// Handle module aliases (if you use them in your app)
"^@/(.*)$": "<rootDir>/src/$1",
},
setupFilesAfterEnv: ["<rootDir>/jest.setup.js"],
testPathIgnorePatterns: ["<rootDir>/node_modules/", "<rootDir>/.next/"],
transform: {
// Use babel-jest to transpile tests with the next/babel preset
"^.+\\.(js|jsx|ts|tsx)$": ["babel-jest", { presets: ["next/babel"] }],
},
transformIgnorePatterns: [
"/node_modules/",
"^.+\\.module\\.(css|sass|scss)$",
],
reporters: [
"default",
process.env.CI === "true" ? "jest-junit" : null,
].filter(Boolean),
};
45 changes: 45 additions & 0 deletions jest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import "@testing-library/jest-dom";

jest.mock("next/router", () => ({
useRouter: () => ({
push: jest.fn(),
replace: jest.fn(),
prefetch: jest.fn(),
back: jest.fn(),
pathname: "/",
query: {},
asPath: "/",
events: {
on: jest.fn(),
off: jest.fn(),
emit: jest.fn(),
},
isFallback: false,
}),
}));

// Mock next/image
jest.mock("next/image", () => ({
__esModule: true,
default: (props) => {
// eslint-disable-next-line jsx-a11y/alt-text
return <img {...props} />;
},
}));

// Mock window.matchMedia
Object.defineProperty(window, "matchMedia", {
writable: true,
value: jest.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // Deprecated
removeListener: jest.fn(), // Deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});

process.env.TZ = "UTC";
Loading