feat: CI
This commit is contained in:
parent
ad42894cd6
commit
19e5133a96
7 changed files with 444 additions and 1 deletions
13
.dockerignore
Normal file
13
.dockerignore
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
node_modules
|
||||
**/node_modules
|
||||
**/dist
|
||||
**/storybook-static
|
||||
**/.storybook-static
|
||||
.git
|
||||
docs
|
||||
.tmp
|
||||
.bun-cache
|
||||
.pw-browsers
|
||||
.pw-libs
|
||||
.shots
|
||||
*.log
|
||||
100
.forgejo/workflows/ci.yml
Normal file
100
.forgejo/workflows/ci.yml
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
name: ci
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: docker
|
||||
container: oven/bun:1
|
||||
steps:
|
||||
- name: Install git
|
||||
run: apt-get update && apt-get install -y git nodejs
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Audit dependencies
|
||||
run: bun audit
|
||||
|
||||
- name: Run unit tests
|
||||
run: bun run test:unit run
|
||||
|
||||
- name: Type check
|
||||
run: bun run type-check -- --force
|
||||
|
||||
- name: Build
|
||||
run: bun run build-only
|
||||
|
||||
- name: Upload dist
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: dist
|
||||
path: packages/library/dist
|
||||
|
||||
publish:
|
||||
needs: build
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
runs-on: docker
|
||||
container: oven/bun:1
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install dependencies
|
||||
run: bun install --frozen-lockfile
|
||||
|
||||
- name: Download dist
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: dist
|
||||
path: packages/library/dist
|
||||
|
||||
- name: Set package version
|
||||
run: bun pm version "${GITHUB_REF_NAME#v}" --no-git-tag-version
|
||||
working-directory: packages/library
|
||||
|
||||
- name: Configure registry auth
|
||||
run: echo "//git.mcpeakdev.com/api/packages/mcpeakdev/npm/:_authToken=${FORGEJO_TOKEN}" > .npmrc
|
||||
working-directory: packages/library
|
||||
env:
|
||||
FORGEJO_TOKEN: ${{ secrets.FORGEJO_TOKEN }}
|
||||
|
||||
- name: Publish package
|
||||
run: bun publish --registry https://git.mcpeakdev.com/api/packages/mcpeakdev/npm/
|
||||
working-directory: packages/library
|
||||
|
||||
publish-docs:
|
||||
needs: build
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
runs-on: docker
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: git.mcpeakdev.com
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.FORGEJO_TOKEN }}
|
||||
|
||||
- name: Extract image tag
|
||||
id: meta
|
||||
run: echo "tag=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Build and push docs image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: packages/playground/Dockerfile
|
||||
push: true
|
||||
tags: |
|
||||
git.mcpeakdev.com/mcpeakdev/nychthemeron-docs:${{ steps.meta.outputs.tag }}
|
||||
git.mcpeakdev.com/mcpeakdev/nychthemeron-docs:latest
|
||||
222
docs/superpowers/plans/2026-06-11-docs-site-and-docker.md
Normal file
222
docs/superpowers/plans/2026-06-11-docs-site-and-docker.md
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
# Docs Site Docker Image + Install Page Implementation Plan
|
||||
|
||||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||||
|
||||
**Goal:** Add an Installation page to the Storybook playground, package the playground's static build as a `nychthemeron-docs` Docker image served by nginx, and wire up CI to build/push that image on version tags.
|
||||
|
||||
**Architecture:** A new MDX docs page (`packages/playground/stories/Install.mdx`) documents installing `@nychthemeron/library` via npm/pnpm/yarn/bun from the private Forgejo npm registry. A new multi-stage `packages/playground/Dockerfile` builds the library and Storybook static output with `oven/bun:1`, then copies `storybook-static` into `nginx:alpine`. A root `.dockerignore` keeps the build context lean. A new `publish-docs` job in `.forgejo/workflows/ci.yml`, parallel to `publish`, builds and pushes the image on `v*` tags.
|
||||
|
||||
**Tech Stack:** Storybook 10 (`@storybook/addon-docs`), Vue 3, Bun, Docker (multi-stage, nginx:alpine), Forgejo Actions.
|
||||
|
||||
---
|
||||
|
||||
### Task 1: Add Installation MDX page
|
||||
|
||||
**Files:**
|
||||
- Create: `packages/playground/stories/Install.mdx`
|
||||
|
||||
- [ ] **Step 1: Create the MDX file**
|
||||
|
||||
```mdx
|
||||
import { Meta } from '@storybook/addon-docs/blocks'
|
||||
|
||||
<Meta title="Get Started/Installation" />
|
||||
|
||||
# Installation
|
||||
|
||||
`@nychthemeron/library` is published to a private npm registry hosted on
|
||||
Forgejo. Configure your package manager for the `@nychthemeron` scope, then
|
||||
install the package.
|
||||
|
||||
## Configure the registry
|
||||
|
||||
Add the following to your project's `.npmrc`:
|
||||
|
||||
```
|
||||
@nychthemeron:registry=https://git.mcpeakdev.com/api/packages/mcpeakdev/npm/
|
||||
```
|
||||
|
||||
## npm
|
||||
|
||||
```bash
|
||||
npm install @nychthemeron/library
|
||||
```
|
||||
|
||||
## pnpm
|
||||
|
||||
```bash
|
||||
pnpm add @nychthemeron/library
|
||||
```
|
||||
|
||||
## yarn
|
||||
|
||||
```bash
|
||||
yarn add @nychthemeron/library
|
||||
```
|
||||
|
||||
## bun
|
||||
|
||||
```bash
|
||||
bun add @nychthemeron/library
|
||||
```
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Build Storybook and verify the page is included**
|
||||
|
||||
Run: `cd packages/playground && bun run build`
|
||||
|
||||
Expected: Build succeeds with output ending in something like
|
||||
`Output directory: storybook-static`. Then run:
|
||||
|
||||
`grep -o '"title":"Get Started/Installation"' packages/playground/storybook-static/index.json`
|
||||
|
||||
Expected: prints `"title":"Get Started/Installation"`.
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add packages/playground/stories/Install.mdx
|
||||
git commit -m "Add installation docs page to playground"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 2: Add root `.dockerignore`
|
||||
|
||||
**Files:**
|
||||
- Create: `.dockerignore`
|
||||
|
||||
- [ ] **Step 1: Create `.dockerignore`**
|
||||
|
||||
```
|
||||
node_modules
|
||||
**/node_modules
|
||||
**/dist
|
||||
**/storybook-static
|
||||
**/.storybook-static
|
||||
.git
|
||||
docs
|
||||
.tmp
|
||||
.bun-cache
|
||||
.pw-browsers
|
||||
.pw-libs
|
||||
.shots
|
||||
*.log
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Commit**
|
||||
|
||||
```bash
|
||||
git add .dockerignore
|
||||
git commit -m "Add .dockerignore for docs Docker build"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 3: Add Dockerfile for the docs site
|
||||
|
||||
**Files:**
|
||||
- Create: `packages/playground/Dockerfile`
|
||||
|
||||
- [ ] **Step 1: Create the Dockerfile**
|
||||
|
||||
```dockerfile
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM oven/bun:1 AS build
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN bun install --frozen-lockfile
|
||||
RUN cd packages/library && bun run build
|
||||
RUN cd packages/playground && bun run build
|
||||
|
||||
FROM nginx:alpine AS runtime
|
||||
COPY --from=build /app/packages/playground/storybook-static /usr/share/nginx/html
|
||||
EXPOSE 80
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Build and run the image locally**
|
||||
|
||||
Run (from repo root):
|
||||
|
||||
```bash
|
||||
docker build -t nychthemeron-docs:test -f packages/playground/Dockerfile .
|
||||
docker run -d --rm --name nychthemeron-docs-test -p 8080:80 nychthemeron-docs:test
|
||||
sleep 2
|
||||
curl -sf http://localhost:8080/ | grep -i storybook
|
||||
docker stop nychthemeron-docs-test
|
||||
```
|
||||
|
||||
Expected: `docker build` completes successfully, the container starts, and
|
||||
the `curl` output contains a reference to `storybook` (from
|
||||
`storybook-static/index.html`).
|
||||
|
||||
> If the Docker CLI/daemon isn't available in the current environment (e.g.
|
||||
> sandboxed dev container), skip running this step here and ask the user to
|
||||
> run it locally before merging.
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add packages/playground/Dockerfile
|
||||
git commit -m "Add Dockerfile for nychthemeron-docs static site"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Task 4: Add `publish-docs` CI job
|
||||
|
||||
**Files:**
|
||||
- Modify: `.forgejo/workflows/ci.yml`
|
||||
|
||||
- [ ] **Step 1: Add the `publish-docs` job**
|
||||
|
||||
Add this job after the existing `publish` job (same indentation level,
|
||||
i.e. as a sibling under `jobs:`):
|
||||
|
||||
```yaml
|
||||
publish-docs:
|
||||
needs: build
|
||||
if: startsWith(github.ref, 'refs/tags/v')
|
||||
runs-on: docker
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Log in to registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: git.mcpeakdev.com
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.FORGEJO_TOKEN }}
|
||||
|
||||
- name: Extract image tag
|
||||
id: meta
|
||||
run: echo "tag=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Build and push docs image
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: packages/playground/Dockerfile
|
||||
push: true
|
||||
tags: |
|
||||
git.mcpeakdev.com/mcpeakdev/nychthemeron-docs:${{ steps.meta.outputs.tag }}
|
||||
git.mcpeakdev.com/mcpeakdev/nychthemeron-docs:latest
|
||||
```
|
||||
|
||||
- [ ] **Step 2: Verify YAML structure**
|
||||
|
||||
Run: `bun run --eval "console.log('ok')"` is not a YAML check — instead,
|
||||
visually confirm in the file that `publish-docs:` is indented exactly like
|
||||
`publish:` (4 spaces under `jobs:`), and that all of its child keys
|
||||
(`needs`, `if`, `runs-on`, `steps`, and each `- name:` step) match the
|
||||
indentation pattern used by the `publish` job. Confirm there are exactly
|
||||
three top-level jobs: `build`, `publish`, `publish-docs`.
|
||||
|
||||
- [ ] **Step 3: Commit**
|
||||
|
||||
```bash
|
||||
git add .forgejo/workflows/ci.yml
|
||||
git commit -m "Add publish-docs job to build and push nychthemeron-docs image"
|
||||
```
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
# Docs site (playground) Docker image + install page
|
||||
|
||||
## Goal
|
||||
|
||||
Publish the Storybook playground as a static "docs" site, package it as a
|
||||
Docker image (`nychthemeron-docs`), and add an Installation page documenting
|
||||
how to install `@nychthemeron/library` from the private Forgejo npm registry
|
||||
via npm, pnpm, yarn, and bun.
|
||||
|
||||
## Install page
|
||||
|
||||
- New file: `packages/playground/stories/Install.mdx`
|
||||
- Storybook addon-docs MDX page (no story export), `Meta` title
|
||||
`Get Started/Installation` so it sorts near the top of the sidebar.
|
||||
- Content:
|
||||
- Heading + short description of the library.
|
||||
- Registry config snippet (`.npmrc`) showing how to point the scoped
|
||||
`@nychthemeron` registry at `https://git.mcpeakdev.com/api/packages/mcpeakdev/npm/`.
|
||||
- Four code blocks showing install commands for `@nychthemeron/library`:
|
||||
npm, pnpm, yarn, bun.
|
||||
|
||||
## Docker image (`nychthemeron-docs`)
|
||||
|
||||
- New file: `packages/playground/Dockerfile`, multi-stage build:
|
||||
- **Stage 1 (`oven/bun:1`)**: copy the workspace, `bun install --frozen-lockfile`,
|
||||
build `@nychthemeron/library` (`cd packages/library && bun run build`),
|
||||
then build Storybook (`cd packages/playground && bun run build` →
|
||||
`packages/playground/storybook-static`).
|
||||
- **Stage 2 (`nginx:alpine`)**: copy `storybook-static` into
|
||||
`/usr/share/nginx/html`, default nginx config, `EXPOSE 80`.
|
||||
- Build context is the repo root (so the workspace lockfile and all
|
||||
packages are available to stage 1).
|
||||
|
||||
## CI changes
|
||||
|
||||
In `.forgejo/workflows/ci.yml`, add a new `publish-docs` job:
|
||||
|
||||
- Parallel to the existing `publish` job (both depend on `build`).
|
||||
- Gated on `startsWith(github.ref, 'refs/tags/v')`.
|
||||
- Steps:
|
||||
1. Checkout
|
||||
2. Log in to `git.mcpeakdev.com` using `docker/login-action` with
|
||||
`secrets.FORGEJO_TOKEN` (same credential as the library publish job).
|
||||
3. Extract version from tag (`${GITHUB_REF_NAME#v}`).
|
||||
4. `docker/build-push-action` with context `.`, dockerfile
|
||||
`packages/playground/Dockerfile`, push `true`, tags:
|
||||
- `git.mcpeakdev.com/mcpeakdev/nychthemeron-docs:<version>`
|
||||
- `git.mcpeakdev.com/mcpeakdev/nychthemeron-docs:latest`
|
||||
|
||||
## Out of scope
|
||||
|
||||
- No changes to the existing `build` or `publish` (npm) jobs beyond what's
|
||||
already in place.
|
||||
- No SPA routing / custom nginx config — Storybook's static output is
|
||||
served as-is.
|
||||
|
|
@ -3,7 +3,7 @@ import { dirname } from 'node:path'
|
|||
import type { StorybookConfig } from '@storybook/vue3-vite'
|
||||
|
||||
const config: StorybookConfig = {
|
||||
stories: ['../stories/**/*.stories.ts'],
|
||||
stories: ['../stories/**/*.stories.ts', '../stories/**/*.mdx'],
|
||||
addons: [getAbsolutePath('@storybook/addon-links'), getAbsolutePath('@storybook/addon-docs')],
|
||||
framework: {
|
||||
name: getAbsolutePath('@storybook/vue3-vite'),
|
||||
|
|
|
|||
12
packages/playground/Dockerfile
Normal file
12
packages/playground/Dockerfile
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
|
||||
FROM oven/bun:1 AS build
|
||||
WORKDIR /app
|
||||
COPY . .
|
||||
RUN bun install --frozen-lockfile
|
||||
RUN cd packages/library && bun run build
|
||||
RUN cd packages/playground && bun run build
|
||||
|
||||
FROM nginx:alpine AS runtime
|
||||
COPY --from=build /app/packages/playground/storybook-static /usr/share/nginx/html
|
||||
EXPOSE 80
|
||||
41
packages/playground/stories/Install.mdx
Normal file
41
packages/playground/stories/Install.mdx
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { Meta } from '@storybook/addon-docs/blocks'
|
||||
|
||||
<Meta title="Get Started/Installation" />
|
||||
|
||||
# Installation
|
||||
|
||||
`@nychthemeron/library` is published to a private npm registry hosted on
|
||||
Forgejo. Configure your package manager for the `@nychthemeron` scope, then
|
||||
install the package.
|
||||
|
||||
## Configure the registry
|
||||
|
||||
Add the following to your project's `.npmrc`:
|
||||
|
||||
```
|
||||
@nychthemeron:registry=https://git.mcpeakdev.com/api/packages/mcpeakdev/npm/
|
||||
```
|
||||
|
||||
## npm
|
||||
|
||||
```bash
|
||||
npm install @nychthemeron/library
|
||||
```
|
||||
|
||||
## pnpm
|
||||
|
||||
```bash
|
||||
pnpm add @nychthemeron/library
|
||||
```
|
||||
|
||||
## yarn
|
||||
|
||||
```bash
|
||||
yarn add @nychthemeron/library
|
||||
```
|
||||
|
||||
## bun
|
||||
|
||||
```bash
|
||||
bun add @nychthemeron/library
|
||||
```
|
||||
Loading…
Reference in a new issue