feat: CI
Some checks failed
ci / build (pull_request) Has been cancelled
ci / publish (pull_request) Has been cancelled
ci / publish-docs (pull_request) Has been cancelled

This commit is contained in:
Matthew McPeak 2026-06-11 16:37:40 -04:00
parent ad42894cd6
commit 19e5133a96
Signed by: McPeakML
GPG key ID: 3D64A2E70F58D07C
7 changed files with 444 additions and 1 deletions

13
.dockerignore Normal file
View 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
View 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

View 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"
```

View file

@ -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.

View file

@ -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'),

View 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

View 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
```