Skip to content
Closed
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
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,5 @@
]
}
},
"initializeCommand": "cp -n ${localWorkspaceFolder}/backend/.env.example ${localWorkspaceFolder}/backend/.env 2>/dev/null || true; cp -n ${localWorkspaceFolder}/backend/.env.local.example ${localWorkspaceFolder}/backend/.env.local 2>/dev/null || true; cp -n ${localWorkspaceFolder}/frontend/.env.example ${localWorkspaceFolder}/frontend/.env 2>/dev/null || true"
"initializeCommand": "bash -c \"cp -n backend/.env.example backend/.env 2>/dev/null || true; cp -n backend/.env.local.example backend/.env.local 2>/dev/null || true; cp -n frontend/.env.example frontend/.env 2>/dev/null || true\""
}
14 changes: 3 additions & 11 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,9 @@ echo " SOBA — Dev Container Setup"
echo "══════════════════════════════════════════════════════════════"
echo ""

# ── Install backend dependencies ────────────────────────────────────────────
echo "==> Installing backend dependencies..."
cd backend
npm ci
cd ..

# ── Install frontend dependencies ─────────────────────────────────────────────
echo "==> Installing frontend dependencies..."
cd frontend
# -- Install root dependencies ─────────────────────────────────────────────
echo "==> Installing root dependencies..."
pnpm install
cd ..

# ── Set up environment file ─────────────────────────────────────────────────
if [ -f backend/.env.example ] && [ ! -f backend/.env ]; then
Expand Down Expand Up @@ -52,7 +44,7 @@ echo " Setup complete!"
echo "══════════════════════════════════════════════════════════════"
echo ""
echo " Quick start:"
echo " Backend: npm run dev --prefix backend (or use launch config 'SOBA Backend')"
echo " Backend: pnpm dev (in backend/) (or use launch config 'SOBA Backend')"
echo " Frontend: pnpm dev (in frontend/) (or use launch config 'SOBA Frontend')"
echo " Both: use compound 'SOBA (Backend + Frontend)'"
echo ""
Expand Down
42 changes: 28 additions & 14 deletions .github/workflows/build-images.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ on:
workflow_dispatch:
inputs:
ref:
description: "Branch, refs/pull/N/head, or SHA (blank = default branch)"
description: "Branch, PR number (e.g. 9), refs/pull/N/head, or SHA (blank = default branch)"
required: false
platforms:
description: "Architectures to build"
Expand All @@ -45,7 +45,7 @@ on:
workflow_call:
inputs:
ref:
description: "Ref to build (e.g. refs/pull/N/head)"
description: "Ref to build (e.g. 9, refs/pull/9/head)"
required: true
type: string
platforms:
Expand All @@ -68,12 +68,20 @@ on:
- "backend/**"
- "frontend/**"
- ".github/workflows/build-images.yaml"
- ".gitignore"
- "package.json"
- "pnpm-lock.yaml"
- "pnpm-workspace.yaml"
push:
branches: [main]
paths:
- "backend/**"
- "frontend/**"
- ".github/workflows/build-images.yaml"
- ".gitignore"
- "package.json"
- "pnpm-lock.yaml"
- "pnpm-workspace.yaml"

env:
REGISTRY: ghcr.io
Expand Down Expand Up @@ -110,25 +118,35 @@ jobs:
if [ -z "$REF" ]; then
REF="${{ github.ref }}"
fi
# Normalize PR number to refs/pull/N/head for manual/call inputs
if echo "$REF" | grep -qE '^[0-9]+$'; then
REF="refs/pull/${REF}/head"
fi
echo "ref=$REF" >> $GITHUB_OUTPUT
echo "platforms=$PLATFORMS" >> $GITHUB_OUTPUT
# Build matrix based on requested platforms
MATRIX='{"include":[]}'
if echo "$PLATFORMS" | grep -q 'amd64'; then
MATRIX=$(echo "$MATRIX" | jq -c '.include += [
{"component":"backend","context":"./backend","platform":"linux/amd64","platform_pair":"linux-amd64","runner":"ubuntu-latest"},
{"component":"frontend","context":"./frontend","platform":"linux/amd64","platform_pair":"linux-amd64","runner":"ubuntu-latest"}
{"component":"backend","dockerfile_dir":"./backend","platform":"linux/amd64","platform_pair":"linux-amd64","runner":"ubuntu-latest"},
{"component":"frontend","dockerfile_dir":"./frontend","platform":"linux/amd64","platform_pair":"linux-amd64","runner":"ubuntu-latest"}
]')
fi
if echo "$PLATFORMS" | grep -q 'arm64'; then
MATRIX=$(echo "$MATRIX" | jq -c '.include += [
{"component":"backend","context":"./backend","platform":"linux/arm64","platform_pair":"linux-arm64","runner":"ubuntu-24.04-arm"},
{"component":"frontend","context":"./frontend","platform":"linux/arm64","platform_pair":"linux-arm64","runner":"ubuntu-24.04-arm"}
{"component":"backend","dockerfile_dir":"./backend","platform":"linux/arm64","platform_pair":"linux-arm64","runner":"ubuntu-24.04-arm"},
{"component":"frontend","dockerfile_dir":"./frontend","platform":"linux/arm64","platform_pair":"linux-arm64","runner":"ubuntu-24.04-arm"}
]')
fi
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
# Use delimiter so JSON is not mangled by GITHUB_OUTPUT parsing
echo "matrix<<MATRIX_EOF" >> $GITHUB_OUTPUT
echo "$MATRIX" >> $GITHUB_OUTPUT
echo "MATRIX_EOF" >> $GITHUB_OUTPUT
if [ "${{ github.event_name }}" = "workflow_call" ] && [ -n "${{ inputs.image_version }}" ]; then
echo "image_version=${{ inputs.image_version }}" >> $GITHUB_OUTPUT
elif [ "${{ github.event_name }}" = "workflow_dispatch" ] && echo "$REF" | grep -q 'refs/pull/'; then
PR_NUM=$(echo "$REF" | sed 's|refs/pull/||;s|/head||')
echo "image_version=pr-${PR_NUM}" >> $GITHUB_OUTPUT
elif [ "${{ github.event_name }}" = "pull_request" ]; then
echo "image_version=pr-${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
elif [ "${{ github.event_name }}" = "workflow_call" ]; then
Expand All @@ -150,9 +168,6 @@ jobs:
fail-fast: false
matrix: ${{ fromJSON(needs.prepare.outputs.matrix) }}
runs-on: ${{ matrix.runner }}
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
Expand All @@ -169,11 +184,13 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# Context = repo root (same as Makefile: docker build -f backend/Dockerfile .)
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
with:
context: ${{ matrix.context }}
context: .
file: ${{ matrix.dockerfile_dir }}/Dockerfile
platforms: ${{ matrix.platform }}
labels: |
org.opencontainers.image.revision=${{ github.sha }}
Expand All @@ -198,9 +215,6 @@ jobs:
merge:
needs: [prepare, build]
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
outputs:
short_sha: ${{ steps.vars.outputs.short_sha }}
image_version: ${{ needs.prepare.outputs.image_version }}
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
.pnpm-store
node_modules
logs_*
.DS_Store
1 change: 1 addition & 0 deletions .husky/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pnpm --workspace-root commitlint --edit "$1"
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pnpm lint
8 changes: 4 additions & 4 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}/backend",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"runtimeExecutable": "pnpm",
"runtimeArgs": ["dev"],
"skipFiles": ["<node_internals>/**"],
"console": "integratedTerminal"
},
Expand All @@ -22,8 +22,8 @@
"type": "node",
"request": "launch",
"cwd": "${workspaceFolder}/frontend",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev", "--", "--hostname", "0.0.0.0"],
"runtimeExecutable": "pnpm",
"runtimeArgs": ["dev", "--hostname", "0.0.0.0"],
"skipFiles": ["<node_internals>/**"],
"console": "integratedTerminal"
},
Expand Down
9 changes: 5 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,16 @@ endif
.PHONY: build build-backend build-frontend

build-backend:
docker build -t $(BACKEND_IMAGE):sha-$(SHORT_SHA) -t $(BACKEND_IMAGE):local \
docker build -f backend/Dockerfile -t $(BACKEND_IMAGE):sha-$(SHORT_SHA) -t $(BACKEND_IMAGE):local \
--label org.opencontainers.image.revision=$(FULL_SHA) \
--label org.opencontainers.image.version=$(IMAGE_VERSION) \
./backend
.

build-frontend:
docker build -t $(FRONTEND_IMAGE):sha-$(SHORT_SHA) -t $(FRONTEND_IMAGE):local \
docker build -f frontend/Dockerfile -t $(FRONTEND_IMAGE):sha-$(SHORT_SHA) -t $(FRONTEND_IMAGE):local \
--label org.opencontainers.image.revision=$(FULL_SHA) \
--label org.opencontainers.image.version=$(IMAGE_VERSION) \
./frontend
.

build: build-backend build-frontend

17 changes: 13 additions & 4 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
FROM node:lts-alpine

# enable pnpm via corepack and ensure workspace installs work
RUN corepack enable pnpm

WORKDIR /app

COPY package*.json ./
RUN npm ci
# copy root workspace config + backend package file
COPY pnpm-lock.yaml pnpm-workspace.yaml package.json ./
COPY backend/package.json backend/

# install only backend deps (hoisted into root node_modules)
RUN pnpm install --filter ./backend...

# copy entire repo and build backend
COPY . .
RUN npx tsc
RUN pnpm --filter ./backend run build

EXPOSE 4000

CMD ["npm", "start"]
# use package manager script to start
CMD ["pnpm", "--filter", "./backend", "start"]
Loading
Loading