Skip to content

Commit 9e359e9

Browse files
committed
ci: Add hosting support files
1 parent 254e904 commit 9e359e9

6 files changed

Lines changed: 319 additions & 0 deletions

File tree

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
name: Docker Build and Publish — API Docs
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- "apps/api-docs/**"
9+
- "libs/flowdrop/api/**"
10+
- ".github/workflows/docker-publish-api-docs.yml"
11+
12+
env:
13+
REGISTRY: ghcr.io
14+
IMAGE_NAME: flowdrop-io/flowdrop-api-docs
15+
16+
jobs:
17+
build-and-push:
18+
name: Build Docker image
19+
runs-on: ubuntu-latest
20+
permissions:
21+
contents: read
22+
packages: write
23+
24+
steps:
25+
- name: Checkout repository
26+
uses: actions/checkout@v4
27+
28+
- name: Set up Docker Buildx
29+
uses: docker/setup-buildx-action@v3
30+
31+
- name: Log in to Container Registry
32+
uses: docker/login-action@v3
33+
with:
34+
registry: ${{ env.REGISTRY }}
35+
username: ${{ github.actor }}
36+
password: ${{ secrets.GITHUB_TOKEN }}
37+
38+
- name: Extract image metadata
39+
id: meta
40+
uses: docker/metadata-action@v5
41+
with:
42+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
43+
tags: |
44+
type=sha,prefix=sha-
45+
type=raw,value=latest,enable={{is_default_branch}}
46+
47+
- name: Build and push
48+
# Build context is repo root — Dockerfile copies libs/flowdrop/api/ at build time
49+
uses: docker/build-push-action@v6
50+
with:
51+
context: .
52+
file: apps/api-docs/Dockerfile
53+
push: true
54+
tags: ${{ steps.meta.outputs.tags }}
55+
labels: ${{ steps.meta.outputs.labels }}
56+
cache-from: type=gha
57+
cache-to: type=gha,mode=max
58+
59+
trigger-deploy:
60+
name: Trigger GitLab deployment
61+
needs: build-and-push
62+
runs-on: ubuntu-latest
63+
if: success() && github.ref == 'refs/heads/main'
64+
65+
steps:
66+
- name: Trigger GitLab pipeline
67+
run: |
68+
curl --fail -X POST \
69+
"https://source.factorial.io/api/v4/projects/1074/trigger/pipeline" \
70+
-F "token=${{ secrets.GITLAB_TRIGGER_TOKEN }}" \
71+
-F "ref=main"
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
name: Docker Build and Publish — Docs
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
paths:
8+
- "apps/docs/**"
9+
- ".github/workflows/docker-publish-docs.yml"
10+
11+
env:
12+
REGISTRY: ghcr.io
13+
IMAGE_NAME: flowdrop-io/flowdrop-docs
14+
15+
jobs:
16+
build-and-push:
17+
name: Build Docker image
18+
runs-on: ubuntu-latest
19+
permissions:
20+
contents: read
21+
packages: write
22+
23+
steps:
24+
- name: Checkout repository
25+
uses: actions/checkout@v4
26+
27+
- name: Set up Docker Buildx
28+
uses: docker/setup-buildx-action@v3
29+
30+
- name: Log in to Container Registry
31+
uses: docker/login-action@v3
32+
with:
33+
registry: ${{ env.REGISTRY }}
34+
username: ${{ github.actor }}
35+
password: ${{ secrets.GITHUB_TOKEN }}
36+
37+
- name: Extract image metadata
38+
id: meta
39+
uses: docker/metadata-action@v5
40+
with:
41+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
42+
tags: |
43+
type=sha,prefix=sha-
44+
type=raw,value=latest,enable={{is_default_branch}}
45+
46+
- name: Build and push
47+
uses: docker/build-push-action@v6
48+
with:
49+
context: apps/docs
50+
push: true
51+
tags: ${{ steps.meta.outputs.tags }}
52+
labels: ${{ steps.meta.outputs.labels }}
53+
cache-from: type=gha
54+
cache-to: type=gha,mode=max
55+
56+
trigger-deploy:
57+
name: Trigger GitLab deployment
58+
needs: build-and-push
59+
runs-on: ubuntu-latest
60+
if: success() && github.ref == 'refs/heads/main'
61+
62+
steps:
63+
- name: Trigger GitLab pipeline
64+
run: |
65+
curl --fail -X POST \
66+
"https://source.factorial.io/api/v4/projects/1074/trigger/pipeline" \
67+
-F "token=${{ secrets.GITLAB_TRIGGER_TOKEN }}" \
68+
-F "ref=main"

apps/api-docs/Dockerfile

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# ============================================================
2+
# FlowDrop API Docs — Docker Build
3+
# ============================================================
4+
# Redocly-generated static site served by nginx.
5+
#
6+
# Build context: repo root (requires libs/flowdrop/api/)
7+
#
8+
# Usage (from repo root):
9+
# docker build -f apps/api-docs/Dockerfile -t flowdrop-api-docs .
10+
# docker run -p 80:80 flowdrop-api-docs
11+
12+
# --- Stage 1: Build ---
13+
FROM node:22-alpine AS builder
14+
15+
# Enable pnpm via corepack
16+
RUN corepack enable && corepack prepare pnpm@latest --activate
17+
18+
WORKDIR /app
19+
20+
# Install dependencies (apps/api-docs only has devDependencies — no lockfile workspace magic)
21+
COPY apps/api-docs/package.json apps/api-docs/pnpm-lock.yaml ./apps/api-docs/
22+
RUN cd apps/api-docs && pnpm install --frozen-lockfile
23+
24+
# Copy source files needed by the build script
25+
COPY apps/api-docs/scripts ./apps/api-docs/scripts
26+
COPY libs/flowdrop/api ./libs/flowdrop/api
27+
28+
ENV NODE_ENV=production
29+
RUN cd apps/api-docs && pnpm run build
30+
31+
32+
# --- Stage 2: Serve ---
33+
FROM nginx:alpine AS server
34+
35+
# Copy built static files
36+
COPY --from=builder /app/apps/api-docs/dist /usr/share/nginx/html
37+
38+
# Copy nginx config
39+
COPY apps/api-docs/nginx.conf /etc/nginx/conf.d/default.conf
40+
41+
EXPOSE 80
42+
43+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
44+
CMD wget -qO- http://localhost/ || exit 1
45+
46+
CMD ["nginx", "-g", "daemon off;"]

apps/api-docs/nginx.conf

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
server {
2+
listen 80;
3+
listen [::]:80;
4+
server_name _;
5+
6+
root /usr/share/nginx/html;
7+
index index.html;
8+
9+
# Enable gzip compression
10+
gzip on;
11+
gzip_vary on;
12+
gzip_proxied any;
13+
gzip_comp_level 6;
14+
gzip_min_length 256;
15+
gzip_types
16+
application/javascript
17+
application/x-javascript
18+
application/json
19+
application/xml
20+
font/eot
21+
font/otf
22+
font/ttf
23+
image/svg+xml
24+
text/css
25+
text/javascript
26+
text/plain
27+
text/xml;
28+
29+
# Try exact file, then directory index, then 404
30+
location / {
31+
add_header Cache-Control "public, max-age=3600";
32+
try_files $uri $uri/ /404.html;
33+
}
34+
35+
# Security headers
36+
add_header X-Frame-Options "SAMEORIGIN" always;
37+
add_header X-Content-Type-Options "nosniff" always;
38+
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
39+
}

apps/docs/Dockerfile

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# ============================================================
2+
# FlowDrop Docs — Docker Build
3+
# ============================================================
4+
# Astro/Starlight static site served by nginx.
5+
#
6+
# Build context: apps/docs/ (standalone app, no workspace deps)
7+
#
8+
# Usage:
9+
# docker build -t flowdrop-docs .
10+
# docker run -p 80:80 flowdrop-docs
11+
12+
# --- Stage 1: Build ---
13+
FROM node:22-alpine AS builder
14+
15+
# Enable pnpm via corepack
16+
RUN corepack enable && corepack prepare pnpm@latest --activate
17+
18+
WORKDIR /app
19+
20+
# Install dependencies first (cached layer)
21+
COPY package.json pnpm-lock.yaml ./
22+
RUN pnpm install --frozen-lockfile
23+
24+
# Copy source and build
25+
COPY astro.config.mjs svelte.config.js tsconfig.json ./
26+
COPY src ./src
27+
COPY public ./public
28+
29+
ENV NODE_ENV=production
30+
RUN pnpm run build
31+
32+
33+
# --- Stage 2: Serve ---
34+
FROM nginx:alpine AS server
35+
36+
# Copy built static files
37+
COPY --from=builder /app/dist /usr/share/nginx/html
38+
39+
# Copy nginx config
40+
COPY nginx.conf /etc/nginx/conf.d/default.conf
41+
42+
EXPOSE 80
43+
44+
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
45+
CMD wget -qO- http://localhost/ || exit 1
46+
47+
CMD ["nginx", "-g", "daemon off;"]

apps/docs/nginx.conf

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
server {
2+
listen 80;
3+
listen [::]:80;
4+
server_name _;
5+
6+
root /usr/share/nginx/html;
7+
index index.html;
8+
9+
# Enable gzip compression
10+
gzip on;
11+
gzip_vary on;
12+
gzip_proxied any;
13+
gzip_comp_level 6;
14+
gzip_min_length 256;
15+
gzip_types
16+
application/atom+xml
17+
application/javascript
18+
application/x-javascript
19+
application/json
20+
application/manifest+json
21+
application/xhtml+xml
22+
application/xml
23+
font/eot
24+
font/otf
25+
font/ttf
26+
image/svg+xml
27+
text/css
28+
text/javascript
29+
text/plain
30+
text/xml;
31+
32+
# Long-term cache for hashed assets (Astro _astro/ directory)
33+
location /_astro/ {
34+
add_header Cache-Control "public, max-age=31536000, immutable";
35+
try_files $uri =404;
36+
}
37+
38+
# Try exact file, then .html extension, then directory index, then 404
39+
location / {
40+
add_header Cache-Control "public, max-age=3600";
41+
try_files $uri $uri.html $uri/ /404.html;
42+
}
43+
44+
# Security headers
45+
add_header X-Frame-Options "SAMEORIGIN" always;
46+
add_header X-Content-Type-Options "nosniff" always;
47+
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
48+
}

0 commit comments

Comments
 (0)