Skip to content
Merged
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
67 changes: 67 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Dependencies
node_modules
.pnpm-store

# Build outputs (will be built in container)
dist
build
*.tsbuildinfo

# Development files
.env
.env.local
.env.development
.env.test

# Testing
coverage
.vitest

# Git
.git
.gitignore
.gitattributes

# IDE
.vscode
.idea
*.swp
*.swo
.DS_Store
Thumbs.db

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

# Turbo
.turbo

# Documentation (not needed in runtime)
docs
README.md
LICENSE

# CI/CD
.github

# Serena
.serena

# Claude
.claude

# Specify
.specify

# Development scripts (not needed in production runtime)

# Docker files (already in image context)
Dockerfile
docker-compose.yml
.dockerignore
17 changes: 17 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Server Configuration
PORT=4000

# Data Path (relative to server package)
# Default points to repository root data folder
DATA_PATH=../../data/structure

# CORS Configuration
# In production, set to your frontend domain(s)
# Example: https://www.freecodecamp.org
# Multiple origins: https://app1.example.com,https://app2.example.com
CORS_ORIGIN=*

# Environment
# Set to 'production' in production environments
# CORS_ORIGIN must be explicitly set when NODE_ENV=production
NODE_ENV=development
63 changes: 63 additions & 0 deletions .github/workflows/docker-docr.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: CD - Docker - DOCR

on:
workflow_dispatch:
inputs:
site_tld:
required: true
type: choice
description: 'Input: The site tld (variant) to build'
options:
- dev
- org
default: 'dev'
workflow_call:
inputs:
site_tld:
required: true
type: string
description: 'Input: The site tld (variant) to build'
outputs:
tagname:
description: 'Output: The tagname for the image built'
value: ${{ jobs.build.outputs.tagname }}

jobs:
build:
name: Build & Push
runs-on: ubuntu-22.04
permissions:
contents: read
outputs:
tagname: ${{ steps.tagname.outputs.tagname }}

steps:
- name: Checkout Source Files
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4

- name: Create a tagname
id: tagname
run: |
tagname=$(git rev-parse --short HEAD)-$(date +%Y%m%d)-$(date +%H%M)
echo "tagname=$tagname" >> $GITHUB_ENV
echo "tagname=$tagname" >> $GITHUB_OUTPUT

- name: Build & Tag Image
run: |
docker build \
--tag registry.digitalocean.com/${{ secrets.DOCR_NAME }}/${{ inputs.site_tld }}/curriculum-db:$tagname \
--tag registry.digitalocean.com/${{ secrets.DOCR_NAME }}/${{ inputs.site_tld }}/curriculum-db:latest \
--file Dockerfile .

- name: Install doctl
uses: digitalocean/action-doctl@58ec81179e2eaa350ef21d4df58f721c81ec2ba2 # v2
with:
token: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }}

- name: Log in to DigitalOcean Container Registry with short-lived credentials
run: doctl registry login --expiry-seconds 1200

- name: Push image to DigitalOcean Container Registry
run: |
docker push registry.digitalocean.com/${{ secrets.DOCR_NAME }}/${{ inputs.site_tld }}/curriculum-db:$tagname
docker push registry.digitalocean.com/${{ secrets.DOCR_NAME }}/${{ inputs.site_tld }}/curriculum-db:latest
206 changes: 206 additions & 0 deletions .github/workflows/node.js-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
name: CI - Node.js

on:
push:
branches:
- 'main'
- 'prod-**'
pull_request:
branches:
- 'main'

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.event.workflow_run.head_branch || github.ref }}
cancel-in-progress: ${{ !contains(github.ref, 'main') && !contains(github.ref, 'prod-') }}

permissions:
contents: read

jobs:
lint:
name: Lint
runs-on: ubuntu-22.04
strategy:
matrix:
node-version: [22]
fail-fast: false

steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4

- name: Check number of lockfiles
run: |
if [ $(find . -name 'package-lock.json' | grep -vc -e 'node_modules') -gt 0 ]
then
echo -e 'Error: found package-lock files in the repository.\nWe use pnpm workspaces to manage packages so all dependencies should be added via pnpm add'
exit 1
fi

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ matrix.node-version }}

- name: Install pnpm
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4
id: pnpm-install
with:
run_install: false

- name: Install dependencies
run: pnpm install

- name: Check formatting
run: |
pnpm format:check || [ $? -eq 1 ] && printf "\nTip: Run 'pnpm run format' in your terminal to fix this.\n\n"

- name: Lint
run: pnpm lint

type-check:
name: Type Check
runs-on: ubuntu-22.04
needs: lint
strategy:
matrix:
node-version: [22]

steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ matrix.node-version }}

- name: Install pnpm
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4
id: pnpm-install
with:
run_install: false

- name: Install dependencies
run: pnpm install

- name: Fetch curriculum data
run: pnpm fetch-data

- name: Generate GraphQL types
run: pnpm codegen

- name: Type check
run: pnpm type-check

build:
name: Build
runs-on: ubuntu-22.04
needs: type-check
strategy:
matrix:
node-version: [22]

steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ matrix.node-version }}

- name: Install pnpm
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4
id: pnpm-install
with:
run_install: false

- name: Install dependencies
run: pnpm install

- name: Fetch curriculum data
run: pnpm fetch-data

- name: Build project
run: pnpm build

- name: Upload build artifacts
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4
with:
name: dist
path: packages/server/dist
retention-days: 7

test:
name: Test
runs-on: ubuntu-22.04
needs: build
strategy:
fail-fast: false
matrix:
node-version: [22]

steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ matrix.node-version }}

- name: Install pnpm
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4
id: pnpm-install
with:
run_install: false

- name: Install dependencies
run: pnpm install

- name: Fetch curriculum data
run: pnpm fetch-data

- name: Run tests
run: pnpm test

test-coverage:
name: Test Coverage
runs-on: ubuntu-22.04
needs: test
strategy:
matrix:
node-version: [22]

steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with:
node-version: ${{ matrix.node-version }}

- name: Install pnpm
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4
id: pnpm-install
with:
run_install: false

- name: Install dependencies
run: pnpm install

- name: Fetch curriculum data
run: pnpm fetch-data

- name: Run tests with coverage
run: pnpm test:coverage

- name: Upload coverage reports
uses: codecov/codecov-action@015f24e6818733317a2da2edd6290ab26238649a # v5
if: always()
with:
files: ./coverage/coverage-final.json
flags: unittests
name: codecov-curriculum-db
Loading