{"id":13729422,"url":"https://github.com/jiro4989/websh","last_synced_at":"2025-05-08T17:09:38.669Z","repository":{"id":39870520,"uuid":"217877724","full_name":"jiro4989/websh","owner":"jiro4989","description":"シェル芸botをWebで使えるようにしたNim製Webアプリ","archived":false,"fork":false,"pushed_at":"2024-01-20T08:48:47.000Z","size":2239,"stargazers_count":69,"open_issues_count":11,"forks_count":5,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-31T17:50:01.633Z","etag":null,"topics":["backend","frontend","nim","webapp"],"latest_commit_sha":null,"homepage":"https://websh.jiro4989.com","language":"Nim","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jiro4989.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2019-10-27T15:46:46.000Z","updated_at":"2024-05-29T17:23:01.000Z","dependencies_parsed_at":"2024-01-20T09:44:08.643Z","dependency_job_id":null,"html_url":"https://github.com/jiro4989/websh","commit_stats":null,"previous_names":[],"tags_count":85,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiro4989%2Fwebsh","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiro4989%2Fwebsh/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiro4989%2Fwebsh/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jiro4989%2Fwebsh/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jiro4989","download_url":"https://codeload.github.com/jiro4989/websh/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253112071,"owners_count":21856070,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backend","frontend","nim","webapp"],"created_at":"2024-08-03T02:00:59.979Z","updated_at":"2025-05-08T17:09:38.176Z","avatar_url":"https://github.com/jiro4989.png","language":"Nim","funding_links":[],"categories":["Execution Environment"],"sub_categories":["Open USP Tsukubai"],"readme":"==========================================\nwebsh - Web shellgei execution environment\n==========================================\n\n.. raw:: html\n\n   \u003ch3 align=\"center\"\u003e\n     \u003cimg src=\"https://github.com/jiro4989/websh/wiki/images/websh_logo.png\" /\u003e\n   \u003c/h3\u003e\n   \u003cp align=\"center\"\u003e\n     \u003ca href=\"https://github.com/jiro4989/websh/releases/latest\"\u003e\u003cimg src=\"https://img.shields.io/github/release/jiro4989/websh.svg\" alt=\"Latest version\" /\u003e\u003c/a\u003e\n     \u003ca href=\"https://github.com/jiro4989/websh/actions\"\u003e\u003cimg src=\"https://github.com/jiro4989/websh/workflows/test/badge.svg\" alt=\"Build Status\" /\u003e\u003c/a\u003e\n     \u003ca href=\"LICENSE\" alt=\"MIT/Apache-2.0 License\"\u003e\u003cimg src=\"https://img.shields.io/badge/licence-MIT%2FApache--2.0-blue?style=flat\" /\u003e\u003c/a\u003e\n   \u003c/p\u003e\n\n| websh はWebブラウザ上でシェル芸botの実行環境を提供するWebアプリです。\n| シェル芸の実行はDockerコンテナ上で行っており、イメージに `シェル芸botのDockerイメージ`_ を使用しています。\n\n※ 2024/01/20 websh を停止しました。現在は静的 HTML を返却する画面だけになっています。\n\n* https://websh.jiro4989.com/\n\n|image-top|\n\n.. contents:: 目次\n\n使い方\n====\n\nブラウザ\n----\n\n* 画面を表示する\n* 画面左のtextareaにシェルを入力する\n* 画面左のRunボタンを押す\n* 結果が画面右のtextareaにセットされる\n* やりたかったらTweetボタンでつぶやく\n\nAPI\n----\n\n実体はフロントエンドのHTMLからAPIリクエストして実行結果を受け取ってるだけです。\nなので普通にcurlでPOSTリクエスト送れば画面がなくても動きます。\n\n以下のようなリクエストを送ればコマンドラインからwebshを使用できます。\n\n.. code-block:: shell\n\n   curl -X POST -d '{\"code\":\"echo hello\", \"images\":[]}' 'https://websh.jiro4989.com/api/shellgei'\n\n`images` にbase64エンコードした画像ファイルを含めるとwebsh上の `/media` 配下にア\nップロードしたファイルがbase64デコードされて配置されます。\n\n詳細なAPI仕様は https://jiro4989.github.io/websh/swagger.html を参照してください\n。\n\nコマンドラインツール\n--------------------\n\n3rd partyのコマンドラインツールが存在します。多謝。\n\nBashライクの操作体系でWebshのAPI経由でシェルを実行するプロンプト。\n\n* https://github.com/sheepla/websh-prompt\n\nコマンドラインでWebshのAPI経由でシェルを実行するCLI。\n\n* https://github.com/Khronos31/scripts/blob/master/bin/websh\n* https://github.com/eggplants/websh.sh\n* https://github.com/sheepla/websh-cli\n* https://github.com/yuu528/sgb\n\n一応自前で作ったコマンドラインツールもある。\n\n* https://github.com/jiro4989/websh-go\n\n動作環境\n====\n\nPCのChrome最新版のみサポートしています。\n\nChrome以外のブラウザでも動くかもしれないですが、動かなくなっても知らないです。\nスマホも動作確認してないので動くかもしれないですし、動かないかもしれないです。\n\nPCのChromeで操作してください。\n\n開発の背景\n====\n\n`シェル芸Bot`_ のWeb移植の SGWeb_ というWebアプリがある。\n\n最新のシェル芸botに追従してなかったので、試しに自分が最新のシェル芸botに追従する\nWebアプリ作って公開してみるか、と思ったから。\nあとWebアプリを作る勉強もかねて。\n\nシステム構成\n============\n\n* フロントエンド\n\n  * Nim_ ( Karax_ )\n\n* バックエンド\n\n  * Nim_ ( Jester_ )\n  * Docker\n\nローカル環境\n------------\n\nアプリはすべてDockerコンテナ上で動作する。\n\nブラウザの画面からシェルを実行するとコンテナ上のNginxへリクエストが流れる。\nNginxはリバースプロキシし、コンテナ上のAPIサーバがリクエストを受ける。\n\nAPIサーバはホストネットワーク上のDockerAPIを使用して、\nシェル芸Botコンテナを操作する。\n\n画像ファイルなどを配置する一時ディレクトリの後始末は\nAPIサーバからは行わず、removerコンテナが非同期に削除する。\n\n.. code-block:: mermaid\n\n   flowchart TD\n       u[developer] --\u003e n[nginx]\n       subgraph PC\n           n --\u003e s[websh_server]\n           subgraph Application\n               s --\u003e fs[file_system]\n               r[websh_remover] --\u003e fs\n           end\n           sgb[ShellGeiBot] --\u003e fs\n       end\n\n本番環境\n---------\n\nInfrastructure as Code (Ansible) している。\nソースコードは infra_ リポジトリ（非公開）で管理。\n\n監視には netdata_ を使っている。\n\n以前はサーバ上にGrafanaLokiと各種PrometheusExporterを入れて、ローカルのGrafana＋\nPrometheusコンテナから監視していたけれど、大掛かり過ぎて外した。あとたまに\nGrafanaLokiのCPUが張り付いて困っていたのもある。\n\n|image-system|\n\n基本設計\n================\n\nブラウザからPOSTリクエストを受け、POSTの内容を取得し、Dockerコンテナ内でシェルを実行する。\n\nコンテナは状態を保持しないようにする。\n一度リクエストをしたあと、再度コンテナにリクエストをしても、前回実行した結果はコンテナ内に残らないようにする。\nリクエストの都度、コンテナを破棄して生成するようにする。\n\nただしコンテナの破棄と生成はAPIサーバプロセス自体は実施しない。\nコンテナの破棄と起動には時間がかかり、合計で約2秒ほどかかってしまう。\nレスポンスタイム向上のため、コンテナの破棄と生成は別プロセスが引き受けるようにする。\nAPIサーバはコンテナの破棄のトリガーを生成するのみに留める。\n\nコンテナの起動はインフラ側のsupervisorが引受ける。\nコンテナや画像ファイルの破棄は別APIサーバとは別プロセスが引き受ける。\n\n以上を踏まえて、Webからのリクエストを受けてレスポンスを返すまでの一連の処理フローは以下の通り。\n\n|image-proc-flow|\n\n開発\n====\n\n前提条件\n--------\n\n以下のツールがインストールされている必要があります。\n\n* Nim_\n* Docker\n* Docker-compose\n\nファイル・ディレクトリ構成\n--------------------------\n\n\n=====================   ========================================\nPath                    Description\n=====================   ========================================\ndocs                    READMEの画像ファイルなど\nnginx                   ローカル開発用のnginxの設定\nwebsh_front             フロントエンドのプログラム\nwebsh_server            バックエンドのAPIサーバのプログラム\nwebsh_remover           バックエンドの後始末を行うプログラム\nDockerfile              アプリのDockerイメージ\ndocker-compose.yml      ローカル開発でのみ使用する開発環境設定\n=====================   ========================================\n\n\n開発環境の起動方法\n------------------\n\nDockerをAPIで操作できるようにする必要がある。\nLinux環境ではSystemdでDockerを起動しているはず。\ndocker.serviceを以下のように修正する。\n\n``/lib/systemd/system/docker.service``\n\n.. code-block:: ini\n\n   # ここを\n   ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock\n\n   # こう修正\n   ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2376 -H fd:// --containerd=/run/containerd/containerd.sock\n\n以下のコマンドをリポジトリディレクトリ配下で実行する。\n\n.. code-block:: shell\n\n   # シェル芸botのイメージを取得 (巨大なので注意)\n   docker pull theoldmoon0602/shellgeibot\n   docker-compose build\n   docker-compose up\n\nサーバを起動して待機状態になったら、ブラウザで以下のページにアクセスする。\n\nhttp://localhost\n\nブランチ運用\n------------\n\n以下の5種類のブランチを使う。\n\n================   =============================================================================\nBranch name        Description\n================   =============================================================================\nmaster             本番用\nfeature/#xx-desc   新機能、UI改善\nhotfix/#xx-desc    バグ修正\nchore/#xx-desc     CIやローカル開発環境の整備など、アプリに影響しない雑多なもの\n================   =============================================================================\n\nfeature, hotfix, choreのブランチ名のプレフィックスは、PR作成時のラベル自動付与にも使用している。\nよって、必ずブランチ命名規則を守ること。\n\n1つずつリリースしたいので各ブランチからmasterにPRを出す。\n複数の改修をまとめてリリースしたい時だけdevelopブランチを使う。\n\nドキュメントの更新だけの場合はmasterブランチから直接pushする。\nこの時は必ずコミットログに `[skip ci]` を含めなければならない。\nmasterブランチのCIが走るとリリースドラフトが生成されてしまうため。\n詳細は CI のセクションを参照。\n\nフロントエンド\n--------------\n\n`websh_frontディレクトリ配下のREADME`_ を参照。\n\nバックエンド\n------------\n\n`websh_serverディレクトリ配下のREADME`_ を参照。\n\nAPI仕様の更新と確認\n----\n\n`public` ディレクトリ配下にWebshのAPI仕様を定義している。\nAPI仕様が変わった場合は、こちらも合わせて更新する。\nAPI仕様はOpenAPI 3.0.2を使用している。\nAPI仕様はGitHub Pagesで閲覧できる。masterブランチが更新されると自動で反映される。\n\n更新したswagger.yamlをローカルで確認する場合は、以下のコマンドを実行してローカル\nでサーバを起動して確認する。\n\n.. code-block:: shell\n\n   $ cd public\n   $ python3 -m http.server\n\nサーバを起動したら http://localhost:8000/swagger.html を開いて画面が期待通り描画\nされるかを確認する。\n\nCI\n----\n\n`.github` ディレクトリ配下にワークフローを定義している。\nビルド、テスト、デプロイのフローは `.github/workflows/main.yml` に定義している。\n\nCIのジョブフローは以下。\n\n|image-ci-flow|\n\nmasterブランチでのpush、margeの場合は `create-tag-draft` が実行される。\n\n`create-tag-draft` ではタグのドラフトを作成する。\nタグのドラフトは、PRの説明から自動でセットされる。\nFeature/BugFixなどの分類は、 PR時のラベルでカテゴライズされる。\n\nPR時のラベルはブランチのプレフィックスから自動でセットされる。\nブランチ命名規則については \u003c\u003c開発,ブランチ運用\u003e\u003e を参照。\n\nタグドラフトをpublishすると `deploy` が実行され、サーバ上にmasterのビルド成果物をデプロイする。\n\nデプロイ方法\n------------\n\n前述のCIの通り、リリースを作成すると自動でデプロイされる。\n\nリリースの下書きはGitHub Actionsが下書きを作成する。\n下書きをpublishすると、GitHub Actionが起動して、デプロイされる。\n以下はデプロイのフロー。\n\n|image-release-flow|\n\nプルリクエスト\n==============\n\nデザインとか超手抜きですので、プルリクエストお待ちしてます。\n\nLICENSE\n=======\n\nApache License\n\n多謝\n====\n\n* `シェル芸Bot`_\n* `シェル芸botのDockerイメージ`_\n* SGWeb_\n\n.. _`シェル芸botのDockerイメージ`: https://github.com/theoremoon/ShellgeiBot-Image\n.. _`シェル芸Bot`: https://github.com/theoremoon/ShellgeiBot\n.. _SGWeb: https://github.com/kekeho/SGWeb\n.. _infra: https://github.com/jiro4989/infra\n.. _`websh_frontディレクトリ配下のREADME`: ./websh_front/README.rst\n.. _`websh_serverディレクトリ配下のREADME`: ./websh_server/README.rst\n.. _`netdata`: https://www.netdata.cloud\n\n.. |image-top| image:: ./docs/top.png\n.. |image-system| image:: ./docs/system.png\n   :alt: システム構成図\n.. |image-proc-flow| image:: ./docs/logic.svg\n   :alt: データ処理フロー\n.. |image-ci-flow| image:: ./docs/ci-main.svg\n   :alt: CIフロー\n.. |image-release-flow| image:: ./docs/release_flow.svg\n   :alt: リリースフロー\n\n.. _Nim: https://nim-lang.org/\n.. _Karax: https://github.com/pragmagic/karax\n.. _Jester: https://github.com/dom96/jester\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjiro4989%2Fwebsh","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjiro4989%2Fwebsh","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjiro4989%2Fwebsh/lists"}