Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
38465f3
chore: migrate project to pnpm and update dependencies
mrbadri Jul 6, 2025
f66038d
refactor: update docker-compose configuration for core-client service
mrbadri Jul 6, 2025
a5502ca
feat: add docker-compose configuration for core-client service
mrbadri Jul 6, 2025
a56d9a0
feat: add environment variables to Dockerfile for base URL configurat…
mrbadri Jul 6, 2025
18fba39
fix: update base URL in coreApi and guestApi to a hardcoded value
mrbadri Jul 6, 2025
42fb53a
feat: enhance authentication components with clipboard OTP functionality
mrbadri Jul 7, 2025
4f355a4
feat: add clipboard permission request functionality to useClipboardO…
mrbadri Jul 7, 2025
724450c
feat: implement clipboard permission listener in useClipboardOtp hook
mrbadri Jul 7, 2025
33292f7
feat: add deploy action
mrbadri Jul 9, 2025
dbde556
feat: add production docker-compose configuration for core-client ser…
mrbadri Jul 9, 2025
75388c3
refactor: update docker-compose configuration for client service
mrbadri Jul 9, 2025
c44ef34
chore: enhance Docker Hub deployment process in workflow
mrbadri Jul 9, 2025
84d2f80
chore: clean up Docker deployment workflow
mrbadri Jul 9, 2025
ce1f8b6
fix: update Docker deployment workflow to pull client service
mrbadri Jul 9, 2025
8253870
chore: remove commented-out Docker build and push steps from deployme…
mrbadri Jul 9, 2025
40fa684
chore: add concurrency configuration to deployment workflow
mrbadri Jul 9, 2025
6e06020
chore: update deployment workflow to use self-hosted runners
mrbadri Jul 9, 2025
e38ce6f
chore: expose port for core service in production Docker Compose
mrbadri Jul 9, 2025
10046db
fix: update API base URLs from HTTPS to HTTP
mrbadri Jul 10, 2025
1a21f6c
refactor: simplify post-login schema transformation and update docker…
mrbadri Jul 10, 2025
1ecb3c2
feat: add development and preview Docker Compose configurations
mrbadri Jul 10, 2025
47b4846
refactor: update PR comment actions in deployment workflow
mrbadri Jul 10, 2025
4ee4a08
chore: update permissions in deployment workflow
mrbadri Jul 10, 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
201 changes: 201 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
name: CI/CD Pipeline

on:
push:
branches:
- main
- dev
pull_request:
types: [opened, synchronize, reopened, closed]

concurrency:
group: "CI-${{ github.ref_name }}-${{ github.event.number || github.sha }}"
cancel-in-progress: true

permissions:
contents: read
pull-requests: write
issues: write

jobs:
# Build job for all scenarios
build:
runs-on: [self-hosted, core]
if: github.event.action != 'closed'
outputs:
image-tag: ${{ steps.image-tag.outputs.tag }}
port: ${{ steps.port.outputs.port }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Determine image tag and port
id: image-tag
run: |
if [ "${{ github.ref_name }}" = "main" ]; then
echo "tag=latest" >> $GITHUB_OUTPUT
elif [ "${{ github.ref_name }}" = "dev" ]; then
echo "tag=dev" >> $GITHUB_OUTPUT
else
echo "tag=pr-${{ github.event.number }}" >> $GITHUB_OUTPUT
fi
- name: Determine port for PR
id: port
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
# Calculate port: 3100 + PR number (ensures unique ports)
PORT=$((3100 + ${{ github.event.number }}))
echo "port=$PORT" >> $GITHUB_OUTPUT
fi
- name: Create .env file
run: |
echo "NEXT_PUBLIC_BASE_URL=${{ secrets.NEXT_PUBLIC_BASE_URL }}" >> .env
echo "NEXT_PUBLIC_BASE_URL_ATTACHMENT=${{ secrets.NEXT_PUBLIC_BASE_URL_ATTACHMENT }}" >> .env
- name: Login to Docker Hub
run: docker login -u mrbadri -p ${{ secrets.DOCKER_TOKEN }}

- name: Build Docker Image
run: |
TAG=${{ steps.image-tag.outputs.tag }}
if [ "${{ github.ref_name }}" = "main" ]; then
docker compose -f docker-compose.prod.yml build
elif [ "${{ github.ref_name }}" = "dev" ]; then
docker compose -f docker-compose.dev.yml build
docker tag mrbadri/pixel-client:dev mrbadri/pixel-client:$TAG
else
# For PR - build and tag
docker build -t mrbadri/pixel-client:$TAG -f ./apps/core/Dockerfile .
fi
- name: Push Docker Image to Docker Hub
run: |
TAG=${{ steps.image-tag.outputs.tag }}
docker push mrbadri/pixel-client:$TAG
# Deploy to production (main branch)
deploy-production:
runs-on: [self-hosted, core]
needs: build
if: github.ref_name == 'main' && github.event_name == 'push'
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Create .env file
run: |
echo "NEXT_PUBLIC_BASE_URL=${{ secrets.NEXT_PUBLIC_BASE_URL }}" >> .env
echo "NEXT_PUBLIC_BASE_URL_ATTACHMENT=${{ secrets.NEXT_PUBLIC_BASE_URL_ATTACHMENT }}" >> .env
- name: Deploy Production
run: |
docker compose -f docker-compose.prod.yml pull client
docker compose -f docker-compose.prod.yml down || true
docker compose -f docker-compose.prod.yml up -d
# Deploy to development (dev branch)
deploy-development:
runs-on: [self-hosted, core]
needs: build
if: github.ref_name == 'dev' && github.event_name == 'push'
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Create .env file
run: |
echo "NEXT_PUBLIC_BASE_URL=${{ secrets.NEXT_PUBLIC_BASE_URL }}" >> .env
echo "NEXT_PUBLIC_BASE_URL_ATTACHMENT=${{ secrets.NEXT_PUBLIC_BASE_URL_ATTACHMENT }}" >> .env
- name: Deploy Development
run: |
docker compose -f docker-compose.dev.yml pull client-dev
docker compose -f docker-compose.dev.yml down || true
docker compose -f docker-compose.dev.yml up -d
# Deploy PR preview
deploy-preview:
runs-on: [self-hosted, core]
needs: build
if: github.event_name == 'pull_request' && github.event.action != 'closed'
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Create .env file
run: |
echo "NEXT_PUBLIC_BASE_URL=${{ secrets.NEXT_PUBLIC_BASE_URL }}" >> .env
echo "NEXT_PUBLIC_BASE_URL_ATTACHMENT=${{ secrets.NEXT_PUBLIC_BASE_URL_ATTACHMENT }}" >> .env
- name: Create PR-specific compose file
run: |
PR_NUMBER=${{ github.event.number }}
PORT=${{ needs.build.outputs.port }}
# Create PR-specific docker-compose file
sed "s/PR_NUMBER/$PR_NUMBER/g; s/PORT_NUMBER/$PORT/g" docker-compose.preview.yml > docker-compose.pr-$PR_NUMBER.yml
- name: Deploy Preview
run: |
PR_NUMBER=${{ github.event.number }}
# Pull the image
docker pull mrbadri/pixel-client:pr-$PR_NUMBER
# Stop and remove existing preview if exists
docker compose -f docker-compose.pr-$PR_NUMBER.yml down || true
# Start the preview
docker compose -f docker-compose.pr-$PR_NUMBER.yml up -d
- name: Comment PR with preview link
uses: marocchino/sticky-pull-request-comment@v2
with:
header: preview-deployment
message: |
### 🚀 Preview Deployed Successfully!
Your pull request preview is now available:
- 📍 **Preview URL**: http://82.115.24.87:${{ needs.build.outputs.port }}
- 🔗 **Container**: `client-preview-${{ github.event.number }}`
- 🐳 **Image**: `mrbadri/pixel-client:pr-${{ github.event.number }}`
This preview will be automatically cleaned up when the PR is closed.
# Cleanup PR preview when closed
cleanup-preview:
runs-on: [self-hosted, core]
if: github.event_name == 'pull_request' && github.event.action == 'closed'
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Cleanup PR preview
run: |
PR_NUMBER=${{ github.event.number }}
# Stop and remove preview containers
docker compose -f docker-compose.pr-$PR_NUMBER.yml down || true
# Remove the compose file
rm -f docker-compose.pr-$PR_NUMBER.yml || true
# Remove the Docker image
docker rmi mrbadri/pixel-client:pr-$PR_NUMBER || true
- name: Post Cleanup Confirmation Comment
if: always()
uses: marocchino/sticky-pull-request-comment@v2
with:
header: preview-cleanup
message: |
### 🧹 Preview Cleanup Complete
All preview deployment resources for this pull request have been successfully removed:
- 🐳 Docker container `client-preview-${{ github.event.number }}` stopped and removed
- 📦 Docker image `mrbadri/pixel-client:pr-${{ github.event.number }}` cleaned up
- 📁 Docker compose file removed
The cleanup process has finished for PR #${{ github.event.number }}.
15 changes: 9 additions & 6 deletions apps/core/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ RUN apk update
RUN apk add --no-cache libc6-compat
# Set working directory
WORKDIR /app
RUN yarn global add turbo
RUN npm install -g pnpm turbo
COPY . .
# RUN npm run prepare:ci
RUN turbo prune core --docker
Expand All @@ -19,13 +19,12 @@ FROM base AS installer
RUN apk update
RUN apk add --no-cache libc6-compat
WORKDIR /app
RUN npm install -g pnpm turbo

# First install the dependencies (as they change less often)
COPY --from=builder /app/out/json/ .
# Configure Yarn with better network settings and use Taobao registry
RUN yarn config set registry https://registry.npmmirror.com/ && \
yarn config set network-timeout 600000 && \
yarn install --network-timeout 600000 --no-network-concurrency
# Configure pnpm with better network settings and use Taobao registry
RUN pnpm install --frozen-lockfile

# Build the project
COPY --from=builder /app/out/full/ .
Expand All @@ -37,7 +36,7 @@ COPY --from=builder /app/out/full/ .
# ARG TURBO_TOKEN
# ENV TURBO_TOKEN=$TURBO_TOKEN

RUN yarn turbo build --filter=core
RUN pnpm turbo build

FROM base AS runner
WORKDIR /app
Expand All @@ -47,6 +46,10 @@ RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
USER nextjs

# Environment variables
ENV NEXT_PUBLIC_BASE_URL=${NEXT_PUBLIC_BASE_URL}
ENV NEXT_PUBLIC_BASE_URL_ATTACHMENT=${NEXT_PUBLIC_BASE_URL_ATTACHMENT}

# Automatically leverage output traces to reduce image size
# https://nextjs.org/docs/advanced-features/output-file-tracing
COPY --from=installer --chown=nextjs:nodejs /app/apps/core/.next/standalone ./
Expand Down
24 changes: 19 additions & 5 deletions apps/core/app/(landing)/_components/mobile-menu/BrowseSheet.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
import {
IconDeviceMobile, IconUsersGroup, IconEye, IconCube, IconVector, IconBox, IconLayout, IconMessage, IconTypography, IconDiamond
import {
IconDeviceMobile,
IconUsersGroup,
IconEye,
IconCube,
IconVector,
IconBox,
IconLayout,
IconMessage,
IconTypography,
IconDiamond,
} from "@tabler/icons-react";

const categories = [
Expand All @@ -18,10 +27,15 @@ const categories = [
const BrowseSheet = () => (
<div className="flex flex-col items-center w-full">
<div className="w-12 h-1.5 bg-[#fff]/20 rounded-full mt-1 mb-4" />
<h2 className="text-2xl font-bold text-white mb-6 w-full text-left">Browse</h2>
<h2 className="text-2xl font-bold text-white mb-6 w-full text-left">
Browse
</h2>
<div className="grid grid-cols-2 gap-x-8 gap-y-5 w-full">
{categories.map((cat) => (
<div key={cat.label} className="flex items-center gap-3 text-white/90 text-base font-medium">
<div
key={cat.label}
className="flex items-center gap-3 text-white/90 text-base font-medium"
>
<span className="bg-[#232228] rounded-md p-2 flex items-center justify-center">
{cat.icon}
</span>
Expand All @@ -32,4 +46,4 @@ const BrowseSheet = () => (
</div>
);

export default BrowseSheet;
export default BrowseSheet;
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,6 @@ const AutherForm = () => {
/>
</div>
<div>

<Textarea
placeholder="Write a short message about yourself"
className=" bg-card h-40 resize-none p-3"
Expand Down
29 changes: 24 additions & 5 deletions apps/core/app/auth/_components/auth-card.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,35 @@
// styles
// props : children
// <authCard> form </authCard>

"use client";
import PixelIcon from "@repo/icons/pxiel";
import { Button } from "@repo/ui/components";
import { ArrowLeft } from "lucide-react";
import { useRouter } from "next/navigation";

import { ReactNode } from "react";

const AuthCard = ({ children }: { children: ReactNode }) => {
const router = useRouter();

const handleBackClick = () => {
router.back();
};

return (
<div className="flex items-center relative z-10 flex-col gap-4 bg-card w-[calc(100% - 32px)] sm:w-[450px] rounded-xl mx-4">
{/* add back button */}
<div className="absolute top-4 left-4 z-10">
<Button
variant="tertiary"
size="icon"
onClick={handleBackClick}
className="hover:bg-secondary/50"
aria-label="Go back"
>
<ArrowLeft size={20} />
</Button>
</div>

{/* logo */}
<div className="w-full px-3 sm:p-7 py-7 flex flex-col items-center gap-4">
<div className="w-full px-3 sm:p-7 py-8 flex flex-col items-center gap-4">
<div>
<PixelIcon size={86} color="currentColor" />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,37 +8,46 @@ import { Button, Input } from "@repo/ui/components";
import { postForgetPasswordSchema } from "@repo/apis/core/accounts/users/forgot-password/post/post-forget-password.schema";
import type { PostForgetPasswordRequest } from "@repo/apis/core/accounts/users/forgot-password/post/post-forget-password.types";
import { UsePostForgetPassword } from "@repo/apis/core/accounts/users/forgot-password/post/use-post-forget-password";
import { useEffect } from "react";

const ForgetPasswordForm = () => {
const router = useRouter();

const form = useForm<PostForgetPasswordRequest>({
resolver: zodResolver(postForgetPasswordSchema.request),
});

const {
register,
formState: { errors },
handleSubmit,
} = form;

const mutation = UsePostForgetPassword({
onSuccess: (res, context) => {
toast.info(res.data.message);
router.replace(`/auth/set-password?username=${context.username}`);
},
onError: (err) => {
toast.error(err.response?.data.message ?? "Something went wrong");
},
});

const onSubmit = (data: PostForgetPasswordRequest) => {
mutation.mutate(data);
};

useEffect(() => {
router.prefetch("/auth/set-password");
}, [router]);

return (
<form onSubmit={handleSubmit(onSubmit)} className="w-full pb-7">
<Input
label="Username"
className="font-normal text-xs"
placeholder="[email protected]"
placeholder="Enter your username"
autoFocus
{...register("username")}
error={errors.username?.message}
/>
Expand Down
Loading