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
8 changes: 8 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
node_modules
.next
coverage
.git
.github
npm-debug.log
.env
.env.*
55 changes: 37 additions & 18 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,33 @@ on:
permissions:
contents: read

concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
test:
name: Type-check, Lint & Test
validate:
name: Validate (Node ${{ matrix.node-version }})
runs-on: ubuntu-latest
permissions:
contents: read
strategy:
fail-fast: false
matrix:
node-version: [20, 22]

steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
fetch-depth: 1

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

- name: Install dependencies
- name: Install dependencies (deterministic)
run: npm ci

- name: Type-check
Expand All @@ -35,28 +44,38 @@ jobs:
- name: Lint
run: npm run lint

- name: Test
- name: Unit and integration tests
run: npm test

build:
name: Build
runs-on: ubuntu-latest
needs: test
permissions:
contents: read
- name: Build
run: npm run build

coverage:
name: Coverage
runs-on: ubuntu-latest
needs: validate
steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
fetch-depth: 1

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
node-version: 20
cache: npm

- name: Install dependencies
run: npm ci

- name: Build
run: npm run build
- name: Coverage tests
run: npm run test:coverage

- name: Upload coverage artifact
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coverage/
if-no-files-found: error
44 changes: 44 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Deploy

on:
workflow_dispatch:
inputs:
image-tag:
description: 'Container image tag to deploy'
required: true
type: string

permissions:
contents: read

jobs:
deploy-staging:
name: Deploy to staging
runs-on: ubuntu-latest
environment: staging

steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
fetch-depth: 1

- name: Deploy placeholder command
run: echo "Deploying image tag ${{ inputs.image-tag }} to staging"

deploy-production:
name: Deploy to production (approval required)
runs-on: ubuntu-latest
needs: deploy-staging
environment: production

steps:
- name: Checkout
uses: actions/checkout@v4
with:
persist-credentials: false
fetch-depth: 1

- name: Deploy placeholder command
run: echo "Deploying image tag ${{ inputs.image-tag }} to production"
114 changes: 114 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
name: Release

on:
push:
tags:
- 'v*.*.*'

permissions:
contents: read

jobs:
verify:
name: Verify release
runs-on: ubuntu-latest
permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm

- name: Install dependencies (deterministic)
run: npm ci

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

- name: Lint
run: npm run lint

- name: Test
run: npm test

- name: Build
run: npm run build

package:
name: Package artifacts
runs-on: ubuntu-latest
needs: verify
permissions:
contents: read

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: npm

- name: Install dependencies
run: npm ci

- name: Build package
run: |
TAG="${GITHUB_REF_NAME}"
export SOURCE_DATE_EPOCH="$(git log -1 --format=%ct)"
npm pack
sha256sum *.tgz > checksums.txt
{
echo "# Release ${TAG}"
echo
echo "## Commit"
echo "- $(git rev-parse HEAD)"
echo
echo "## Checksums"
cat checksums.txt
} > release-notes.md

- name: Upload release artifacts
uses: actions/upload-artifact@v4
with:
name: release-artifacts
path: |
*.tgz
checksums.txt
release-notes.md
if-no-files-found: error

publish:
name: Publish GitHub release
runs-on: ubuntu-latest
needs: package
permissions:
contents: write

steps:
- name: Download artifacts
uses: actions/download-artifact@v4.1.3
with:
name: release-artifacts

Comment on lines +103 to +107
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
body_path: release-notes.md
files: |
*.tgz
checksums.txt
25 changes: 25 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
FROM node:20-bookworm-slim AS deps
WORKDIR /app
COPY package*.json ./
RUN npm ci

FROM node:20-bookworm-slim AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

FROM node:20-bookworm-slim AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1

COPY package*.json ./
RUN npm ci --omit=dev

COPY --from=builder /app/.next ./.next
COPY --from=builder /app/public ./public
COPY --from=builder /app/next.config.mjs ./next.config.mjs

EXPOSE 3000
CMD ["npm", "run", "start"]
Loading
Loading