Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

chabokan-ctl

chabokan-ctl logo

English · فارسی

CI Python 3.11+ License: MIT Version Tests

Generic deploy toolkit for Chabokan PaaS — stage/package → FTP (manifest) → content-only restart → Hub logs → HTTP health. English-only CLI. Project names, Hub services, and FTP targets come from your chabokan.project.yaml + env — nothing customer-specific is hard-coded.

Quick links: Quick Start · Configure · Commands · False-restart defense · Architecture · Docs · فارسی · Contributing · Security · License


What it is

chabokan-ctl is a production-grade Python CLI and optional Tk menu for teams deploying to Chabokan (Iranian PaaS). It wraps the repetitive, error-prone parts of FTP sync, Hub API calls, log analysis, billing visibility, and health checks into one Rich-powered workflow.

stage/package → FTP (manifest) → content-only restart → Hub logs → HTTP health

Built for developers who need repeatable ships, false-restart defense, and honest FTP verify — not another bash script that restarts on every metadata touch.

Created by Ali Rashidi. MIT-licensed generic toolkit hardened from production Chabokan deploy workflows.


Table of contents


Why chabokan-ctl

Pain on Chabokan What chabokan-ctl does
Manual FTP + panel restarts chabokan ship all — staged upload, verify, conditional restart
Restarts on PACKAGE.txt timestamp changes Stable fingerprint manifest + content-only restart policy
“0 uploaded / N skipped” but stale remote RETR-MD5 verify; manifest is a hint, not skip authority
Orphan purge deleting uploads/logs Path normalization + mass-delete guard (≥50% abort)
Hub logs vanish after restart chabokan file-logs pulls persistent FTP logs/
Opaque deploy failures Pre-deploy log audit, post-deploy issue table, doctor
Windows Persian terminal garble Optional rtl-probe; English product UI by default

Features

Area Capabilities
Ship / deploy Stage tree, parallel MD5, FTP upload/skip, verify, restart policy, /api/ready gate, safe web skip
Hub API Service logs, restart, credentials fetch (redacted by default), billing/cost
FTP MLSD index, parallel RETR, orphan purge with safety guards, preserve prefixes
Logs Pre-deploy audit, post-deploy analysis, persistent file-logs pull
Health Stack-aware probes (python-fastapi, nginx-static, nextjs, …)
CLI UX Typer + rich-click, --plain / --json, usage-assist for common mistakes
Menu / GUI chabokan menu (Tk on Windows), result dialogs after doctor/ship
Safety Atomic safety matrix tests, contract tests for PACKAGE.txt stability
i18n lab rtl-probe for Persian terminal display experiments (not product UI)

Architecture

High-level module map (see docs/architecture.md):

cli/     Typer + rich-click entrypoint
core/    config, credentials, API client, project YAML
ftp/     FTP client + restart_policy
ship/    pipeline, staging
logs/    build_state, analysis, display
ui/      console, theme, stylekit, RTL, menu
health/  parallel HTTP probes
billing/ wallet / cost helpers
platform/ stack profiles
flowchart TB
  subgraph cli [CLI layer]
    TY[Typer / rich-click]
    MENU[Tk menu optional]
  end

  subgraph core [Core]
    CFG[chabokan.project.yaml]
    ENV[.env.chabokan secrets]
    API[Hub API client]
  end

  subgraph ship [Ship pipeline]
    STG[Stage / package]
    FTP[FTP sync + verify]
    RST[Restart policy]
    HLTH[Health probes]
  end

  subgraph obs [Observability]
    LOGS[Log analysis]
    DOC[Doctor / monitor]
    BILL[Billing tables]
  end

  TY --> CFG
  TY --> ENV
  TY --> STG
  STG --> FTP
  FTP --> RST
  RST --> API
  API --> LOGS
  LOGS --> DOC
  API --> BILL
  RST --> HLTH
  MENU --> TY
Loading

REPO_ROOT is detected by walking parents for chabokan.project.yaml (or chabokan.project.example.yaml). Works from application repos, monorepo packages/ layouts, or this standalone checkout.


Ship pipeline

End-to-end flow for chabokan ship all:

sequenceDiagram
  participant Dev as Developer
  participant CTL as chabokan-ctl
  participant Stage as Local stage
  participant FTP as Chabokan FTP
  participant Hub as Chabokan Hub API
  participant App as Running service

  Dev->>CTL: chabokan ship all
  CTL->>Stage: stage_service (package tree)
  CTL->>FTP: classify + upload changed files
  CTL->>FTP: RETR-MD5 verify (skip authority)
  alt content changed
    CTL->>Hub: restart service
    CTL->>Hub: tail build/runtime logs
    CTL->>App: HTTP health wait
  else metadata only
    CTL-->>Dev: Restart skipped — metadata only
  end
  CTL-->>Dev: Deploy recap + cost/wallet (optional)
Loading

Three-layer PACKAGE.txt defense (see docs/ftp-and-restart.md):

  1. Stable contentContent-Fingerprint from sorted path+size; no Generated: timestamp.
  2. UTF-8 no BOM — PowerShell must not write EF BB BF.
  3. Skip + content restart — default ftp_skip_paths includes PACKAGE.txt; metadata basenames ignored for restart decisions.

Split deploy (API + web) — v2.0.6+

When API and frontend are separate Chabokan services:

chabokan ship api  →  GET /api/ready = 200  →  chabokan ship web

web_ship_blocked_by_api() skips web in the same batch if API deploy failed or /api/ready did not pass (api_deploy_failed / api_health_not_ready). /api/health is stealth ops info only — not a ship gate.

Ops runbook: docs/ops/deploy-recovery-runbook.md · FA


Repository layout

chabokan-ctl/
├── src/chabokan_ctl/     # Python package (59 modules)
├── tests/                # 287 unit/contract tests (+ 2 opt-in live)
├── docs/                 # MkDocs + README map
├── scripts/              # chabokan.ps1 Windows helper
├── chabokan.project.yaml # Dev/test profile (generic myapp)
├── chabokan.project.example.yaml
├── pyproject.toml        # Hatchling, chabokan entry point
├── mkdocs.yml
└── .github/workflows/    # CI (pytest, ruff, build)

Prerequisites

Requirement Notes
Python 3.11+ 3.12 supported in CI matrix
Chabokan Hub account API token + per-service FTP credentials
Application repo With deployable tree (Docker / static / FastAPI, etc.)
Windows (optional) Tk menu + scripts/chabokan.ps1 UTF-8 helper

Quick start

git clone https://github.com/Ali-Rashidi-80/chabokan-ctl.git
cd chabokan-ctl
pip install -e ".[dev]"
chabokan --help

Wire your app repo:

cp chabokan.project.example.yaml /path/to/your-app/chabokan.project.yaml
# edit services, URLs, FTP roots
cp .env.chabokan.example /path/to/your-app/.env.chabokan
# fill CHABOKAN_* secrets (gitignore .env.chabokan)
cd /path/to/your-app
chabokan preflight all
chabokan ship all

Install

pip install -e .
# or from PyPI (when published):
# pip install chabokan-ctl
chabokan --help

Windows helper (optional, sets UTF-8):

.\scripts\chabokan.ps1 --help

Configure

  1. Copy chabokan.project.example.yaml to chabokan.project.yaml at your application repo root. For every Chabokan stack type (Python, Node, PHP, DB, MinIO, …) see the full reference chabokan.project.yaml in this repo.
  2. Create .env.chabokan (gitignored) with CHABOKAN_API_TOKEN and FTP vars.
  3. Run chabokan preflight all.

Example env keys (see .env.chabokan.example):

CHABOKAN_API_TOKEN=...
CHABOKAN_API_FTP_HOST=...
CHABOKAN_API_FTP_USER=...
CHABOKAN_API_FTP_PASS=...
CHABOKAN_WEB_FTP_HOST=...
CHABOKAN_WEB_FTP_USER=...
CHABOKAN_WEB_FTP_PASS=...

Credentials fetch (redacted by default):

chabokan credentials fetch my-wp-service
chabokan credentials fetch my-wp-service --show-secrets  # intentional reveal only

Commands

Command Purpose
chabokan menu Interactive help
chabokan ship all Full pipeline
chabokan doctor api Logs + HTTP
chabokan file-logs api FTP persistent logs
chabokan monitor Cost + health
chabokan rtl-probe Optional terminal RTL lab

Extended groups (see docs/commands.md):

Group Examples
menu (help) chabokan menu, chabokan menu ship, chabokan menu --no-gui
ship / deploy chabokan ship all, chabokan deploy web --wait
preflight / audit chabokan preflight all, chabokan predeploy-audit
service chabokan service logs api --tail 80, chabokan services list
credentials chabokan credentials fetch wp
ftp chabokan ftp test web, chabokan ftp sync api
doctor chabokan doctor all, chabokan doctor api --source both
cost / monitor chabokan cost, chabokan monitor
package chabokan package web --no-zip

Global flags: --plain, --rtl auto|shaped|visual|on|off, --json, --gui/--no-gui, --env-file, --verbose.


False-restart defense

Stable PACKAGE.txt (no timestamp), UTF-8 without BOM, restart only when content paths change. Metadata-only syncs print:

Restart skipped — metadata only

No Restarting … line when only metadata would upload.

When FTP content is unchanged but you need a Docker rebuild:

chabokan ship api --force-restart

Full policy: docs/ftp-and-restart.md.


Testing

pip install -e ".[dev]"
pytest -q
ruff check src tests
black --check src tests
isort --check-only src tests
mypy src/chabokan_ctl
python -m compileall -q src tests

Windows one-shot (mirrors CI):

.\scripts\run-qa.ps1
Suite Count Notes
Unit + contract 287 Default CI; no network
Skipped live 2 Opt-in Hub/FTP
Live Hub opt-in CHABOKAN_LIVE_TESTS=1 — use a non-production project only

Smoke commands (from ACCEPTANCE.md):

chabokan --help
chabokan menu --no-gui
chabokan rtl-probe --json-out

Documentation map

Document Description
docs/README.md Documentation index
docs/getting-started.md First-time setup
docs/architecture.md Module map
docs/commands.md Command reference
docs/ftp-and-restart.md FTP verify + restart policy
docs/gui-and-menu.md Tk menu + dialogs
docs/i18n-persian.md RTL probe notes
docs/stacks.md Platform stack profiles
docs/ops/deploy-recovery-runbook.md Split API/web ops (EN)
docs/ops/deploy-recovery-runbook.fa.md راهنمای بازیابی deploy (FA)
docs/migration-v2.md v1 scripts → v2 package
CHANGELOG.md Release history
ACCEPTANCE.md Definition of done

Build MkDocs site locally:

pip install -e ".[dev]"
mkdocs serve

FAQ

Is this tied to one customer project?
No. v2.0.5+ loads services only from your YAML. No hard-coded tenant or service names.

Why English-only UI?
Mixed FA/EN in Click help columns breaks BiDi box borders on Windows Terminal. Persian remains available via rtl-probe for terminal experiments.

Can I use it from a monorepo?
Yes. Install with pip install -e packages/chabokan-ctl and place chabokan.project.yaml at the monorepo root. See docs/dual-repo.md for optional mirror sync.

Does ship always restart?
Only when FTP content changed (RETR-MD5 proven). Metadata-only uploads skip restart.


Troubleshooting

Symptom Likely cause Fix
Missing .env.chabokan Secrets file not created Copy .env.chabokan.example, fill values
Restart skipped — metadata only Only PACKAGE/manifest changed Expected; use --force-restart if image rebuild needed
FTP verify failures after purge Path normalization mismatch (historical) Upgrade ≥2.0.2; check preserve prefixes
Persian garbage in terminal Wrong RTL strategy Run chabokan rtl-probe; set CHABOKAN_RTL=logical
Empty --help rows Old rich-click Upgrade package ≥2.0.4

Security

  • Never commit .env.chabokan, production tokens, or FTP passwords.
  • credentials fetch redacts secrets unless --show-secrets is explicit.
  • Report vulnerabilities per SECURITY.md — do not open public issues with exploit details.

Contributing

See CONTRIBUTING.md and docs/contributing.md. PRs welcome for bug fixes, docs, and safety improvements. Live ship tests must use a dedicated sandbox project.


License

MIT — see LICENSE.


Contact

About

Generic Chabokan PaaS deploy CLI — FTP sync, content-only restart, Hub API, Rich UI. Python 3.11+. EN/FA docs.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages