نسخه آنلاین در حال بارگذاری زمان... تهران: ۲۶°C
۲۸ کاربر آنلاین

PNo.30Light

نشریه تخصصی هوش مصنوعی، سیستم‌های سرور و مهندسی داده

تازه ترین‌ها
توسعه وب
زمان مطالعه: ۲۰ دقیقه ۰ بازدید

MkDocs: مستندسازی چندپروژه‌ای و deploy خودکار در CI/CD

نویسنده: تحریریه فنی P30Light
MkDocs: مستندسازی چندپروژه‌ای و deploy خودکار در CI/CD
✦ خلاصه نکات کلیدی مقاله
  • MkDocs + Material: Markdown → سایت مستندات استاتیک با جستجو، dark mode و nav چندسطحی.
  • monorepo-plugin برای چند mkdocs.yml در یک repo؛ multirepo-plugin برای ادغام docs از چند Git repository.
  • Pipeline با path filter: فقط وقتی docs/ تغییر کند build و deploy شود — بدون waste CI.

تیم‌هایی که چند سرویس، چند API، یا چند محصول دارند، زود به این مشکل می‌خورند: مستندات یا پراکنده است (READMEهای قدیمی، Confluence، Notion) یا دور از کد نگه‌داری می‌شود. MkDocs یکی از ساده‌ترین راه‌ها برای تبدیل Markdown به سایت مستندات حرفه‌ای است — و با دو plugin کلیدی می‌توانید چند منبع doc را در یک portal ادغام کنید و با CI/CD هر push را خودکار publish کنید.

در این مقاله: MkDocs از صفر، الگوهای multi-docs، و pipeline آماده production.


MkDocs چیست؟

MkDocs یک static site generator پایتونی است که:

  • فایل‌های Markdown در پوشه docs/ را می‌خواند
  • از mkdocs.yml برای nav، theme و plugin استفاده می‌کند
  • خروجی HTML استاتیک در site/ می‌سازد
  • با mkdocs serve live reload دارد

چرا MkDocs؟

مزیتتوضیح
سادگیYAML + Markdown — بدون React/Vue
سرعتbuild چند ثانیه برای doc متوسط
ecosystemصدها plugin (search، versioning، multirepo)
Material themeUI مدرن، جستجو، RTL، dark mode
CI-friendlymkdocs build در هر pipeline

برای API docs سنگین OpenAPI شاید Redoc/Swagger UI جدا لازم باشد؛ برای راهنمای داخلی، runbook، و architecture doc — MkDocs عالی است.


شروع سریع: یک پروژه MkDocs

نصب

python3 -m venv .venv
source .venv/bin/activate
pip install mkdocs mkdocs-material

ساختار پایه

my-docs/
├── docs/
│   ├── index.md
│   └── getting-started.md
├── mkdocs.yml
└── requirements.txt

mkdocs.yml نمونه

site_name: My Platform Docs
site_url: https://docs.example.com
repo_url: https://github.com/org/my-docs
edit_uri: edit/main/docs/

theme:
  name: material
  language: fa
  features:
    - navigation.tabs
    - navigation.sections
    - search.suggest
    - content.code.copy
  palette:
    - scheme: default
      primary: indigo
      toggle:
        icon: material/brightness-4
        name: Dark mode
    - scheme: slate
      primary: indigo
      toggle:
        icon: material/brightness-7
        name: Light mode

plugins:
  - search

nav:
  - Home: index.md
  - شروع: getting-started.md

markdown_extensions:
  - admonition
  - pymdownx.highlight
  - pymdownx.superfences
  - pymdownx.tabbed:
      alternate_style: true
  - toc:
      permalink: true

اجرا

mkdocs serve        # http://127.0.0.1:8000
mkdocs build        # خروجی در site/

requirements.txt (برای CI)

mkdocs>=1.6
mkdocs-material>=9.5

multi-docs یعنی چه؟

سه سناریوی رایج:

سناریوراه‌حل
یک repo، چند تیم، چند پوشه docmkdocs-monorepo-plugin
چند repo جدا، یک portal مرکزیmkdocs-multirepo-plugin
نسخه‌های v1/v2/v3 APImike (versioning)

روش ۱: Monorepo — چند mkdocs.yml در یک repository

وقتی monorepo دارید (مثلاً services/api، services/worker، infra/terraform)، هر تیم docs/ و mkdocs.yml خودش را نگه می‌دارد و یک root site همه را merge می‌کند.

Plugin: mkdocs-monorepo-plugin (از Backstage/Spotify)

ساختار نمونه

platform-monorepo/
├── mkdocs.yml                 # root — portal اصلی
├── docs/
│   └── index.md
├── services/
│   ├── api/
│   │   ├── mkdocs.yml
│   │   └── docs/
│   │       └── index.md
│   └── worker/
│       ├── mkdocs.yml
│       └── docs/
│           └── index.md
└── requirements.txt

root mkdocs.yml

site_name: Platform Documentation
theme:
  name: material

plugins:
  - monorepo

nav:
  - Home: 'index.md'
  - API Service: '!include services/api/mkdocs.yml'
  - Worker Service: '!include services/worker/mkdocs.yml'

services/api/mkdocs.yml

site_name: API Service
nav:
  - Overview: 'index.md'
  - Authentication: 'auth.md'
  - Endpoints: 'endpoints.md'

مزایا:

  • doc کنار کد همان سرویس
  • CODEOWNERS per folder
  • mkdocs serve در subfolder فقط doc همان تیم
cd services/api && mkdocs serve   # فقط API docs
cd ../../ && mkdocs serve         # کل portal

روش ۲: Multirepo — ادغام doc از چند Git repository

وقتی سرویس‌ها repo جدا دارند ولی می‌خواهید یک docs.example.com داشته باشید:

Plugin: mkdocs-multirepo-plugin

root mkdocs.yml

site_name: Company Docs Portal
theme:
  name: material

plugins:
  - multirepo

nav:
  - Home: index.md
  - Imported Repos:
      - Backend API: '!import https://github.com/org/backend-api?branch=main&docs_dir=docs/*'
      - Frontend App: '!import https://github.com/org/frontend-app?branch=main&docs_dir=docs/*'
      - Infra: '!import https://github.com/org/infra?branch=main&docs_dir=docs/*'

در build، plugin repoها را clone می‌کند، docs/ را import می‌کند، site واحد می‌سازد.

نکته CI: برای private repoها token لازم است:

CIمتغیر محیطی
GitHub ActionsGithubAccessToken
GitLab CIGitlabCIJobToken
Azure PipelinesAccessToken

روش ۳: یک repo — nav چندبخشی (بدون plugin)

برای پروژه‌های کوچک‌تر، فقط nav گسترده کافی است:

nav:
  - Home: index.md
  - Platform:
      - Architecture: platform/architecture.md
      - Security: platform/security.md
  - Services:
      - API: services/api.md
      - Worker: services/worker.md
  - Runbooks:
      - Incident Response: runbooks/incident.md
      - Deploy: runbooks/deploy.md

ساده‌ترین حالت — بدون merge چند mkdocs.yml.


Versioning با mike (اختیاری)

برای doc چندنسخه (API v1، v2):

pip install mike
mike deploy 1.0 latest --update-alias
mike set-default latest

در mkdocs.yml:

extra:
  version:
    provider: mike

مناسب کتابخانه‌های public؛ برای internal docs معمولاً branch main کافی است.


Pipeline خودکار: GitHub Actions

هر push به main که docs/ یا mkdocs.yml تغییر کند → build → deploy.

.github/workflows/docs.yml

name: Build and Deploy MkDocs

on:
  push:
    branches: [main]
    paths:
      - 'docs/**'
      - 'mkdocs.yml'
      - 'requirements.txt'
      - 'services/**/docs/**'
      - 'services/**/mkdocs.yml'
      - '.github/workflows/docs.yml'
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

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

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - uses: actions/setup-python@v5
        with:
          python-version: '3.12'
          cache: pip
          cache-dependency-path: requirements.txt

      - name: Install dependencies
        run: pip install -r requirements.txt

      - name: Build MkDocs
        env:
          # فقط اگر multirepo-plugin و repo خصوصی دارید:
          GithubAccessToken: ${{ secrets.DOCS_REPO_TOKEN }}
        run: mkdocs build --strict

      - uses: actions/configure-pages@v4

      - uses: actions/upload-pages-artifact@v3
        with:
          path: site/

  deploy:
    needs: build
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    steps:
      - id: deployment
        uses: actions/deploy-pages@v4

--strict: اگر link شکسته یا warning باشد، build fail — doc شکسته deploy نمی‌شود.

paths filter: push روی src/app.py pipeline doc را اجرا نمی‌کند.


Pipeline: GitLab CI + deploy به nginx

برای self-hosted (مثل سرور nginx):

.gitlab-ci.yml

stages:
  - build
  - deploy

variables:
  PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"

cache:
  paths:
    - .cache/pip

build-docs:
  stage: build
  image: python:3.12-slim
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      changes:
        - docs/**/*
        - mkdocs.yml
        - requirements.txt
        - services/**/docs/**/*
        - services/**/mkdocs.yml
  script:
    - pip install -r requirements.txt
    - mkdocs build --strict
  artifacts:
    paths:
      - site/
    expire_in: 1 day

deploy-docs:
  stage: deploy
  image: alpine:latest
  needs: [build-docs]
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
      changes:
        - docs/**/*
        - mkdocs.yml
        - requirements.txt
  before_script:
    - apk add --no-cache openssh-client rsync
    - eval $(ssh-agent -s)
    - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - mkdir -p ~/.ssh && chmod 700 ~/.ssh
    - ssh-keyscan -p 667 docs-server.example.com >> ~/.ssh/known_hosts
  script:
    - rsync -avz --delete -e "ssh -p 667" site/ [email protected]:/var/www/docs/
  environment:
    name: production
    url: https://docs.example.com

Secrets در GitLab: SSH_PRIVATE_KEY در Settings → CI/CD → Variables.


Pipeline: Multirepo با token

اگر mkdocs-multirepo-plugin دارید، در GitHub Actions:

      - name: Build MkDocs (multirepo)
        env:
          GithubAccessToken: ${{ secrets.DOCS_REPO_TOKEN }}
        run: mkdocs build --strict

Token باید read روی همه repoهای import شده داشته باشد. در GitLab از CI_JOB_TOKEN با تنظیم CI/CD job token scope استفاده کنید.


requirements.txt کامل (monorepo + multirepo)

mkdocs>=1.6.0
mkdocs-material>=9.5.0
mkdocs-monorepo-plugin>=1.1.0
mkdocs-multirepo-plugin>=0.8.0
mike>=2.0.0

Pin نسخه‌ها در production تا build قابل تکرار بماند.


الگوی پیشنهادی برای تیم

┌─────────────────────────────────────────────────────────┐
│  Developer writes Markdown next to code                 │
│  services/api/docs/  +  services/api/mkdocs.yml         │
└────────────────────────┬────────────────────────────────┘
                         │ git push

┌─────────────────────────────────────────────────────────┐
│  CI: path filter → pip install → mkdocs build --strict  │
└────────────────────────┬────────────────────────────────┘

         ┌───────────────┼───────────────┐
         ▼               ▼               ▼
   GitHub Pages    nginx/rsync    S3 + CloudFront

checklist production

موردانجام
requirements.txt pinned
mkdocs build --strict در CI
path filter در pipeline
edit_uri برای «Edit on GitHub»
search plugin فعال
HTTPS + custom domain
PR preview (اختیاری)build در MR بدون deploy

PR preview (GitLab/GitHub)

# job جدا — فقط artifact، بدون deploy
preview-docs:
  rules:
    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
  script:
    - pip install -r requirements.txt
    - mkdocs build
  artifacts:
    paths: [site/]

Reviewer لینک artifact را باز می‌کند قبل از merge.


MkDocs vs Sphinx vs Docusaurus

ابزارزبانمناسب برای
MkDocsPythoninternal docs، runbooks، سریع
SphinxPythondoc علمی، Python packages
DocusaurusReact/MDXproduct docs با component سنگین
GitBookSaaSتیم بدون DevOps

برای تیم DevOps/Platform که Markdown و CI بلد است — MkDocs + Material + monorepo plugin معمولاً سریع‌ترین مسیر است.


نکات فارسی / RTL

Material theme از RTL پشتیبانی می‌کند:

theme:
  name: material
  language: fa
  direction: rtl

برای مخلوط فارسی + code block انگلیسی، pymdownx.superfences و content.code.copy کافی است.


Troubleshooting رایج

مشکلراه‌حل
nav file not foundمسیر نسبی از docs/ درست باشد
multirepo clone failtoken و env var نام درست
monorepo !include errorهر sub mkdocs.yml syntax معتبر
build کندpath filter؛ cache pip در CI
link شکستهmkdocs build --strict locally قبل push

جمع‌بندی

MkDocs برای تبدیل Markdown به portal مستندات حرفه‌ای کافی است. برای multi-docs:

  1. یک repo بزرگmkdocs-monorepo-plugin + !include
  2. چند repomkdocs-multirepo-plugin + !import
  3. ساده → nav گسترده در یک mkdocs.yml

Pipeline خودکار:

  • paths filter فقط روی docs/
  • requirements.txt + cache
  • mkdocs build --strict
  • deploy به GitHub Pages، nginx، یا object storage

مستندات کنار کد + deploy خودکار = doc همیشه به‌روز — بدون Confluence قدیمی.

قدم بعدی

pip install mkdocs mkdocs-material mkdocs-monorepo-plugin
mkdocs new my-platform-docs
# mkdocs.yml را تنظیم کنید
# .github/workflows/docs.yml را اضافه کنید
git push

منابع:


منتشر شده در P30Light — بخش DevOps و توسعه وب.

لینک گزارش با موفقیت کپی گردید!