{"id":26615775,"url":"https://github.com/snickerjp/lifecycle-manager","last_synced_at":"2025-03-24T06:33:58.540Z","repository":{"id":283285227,"uuid":"951264374","full_name":"snickerjp/lifecycle-manager","owner":"snickerjp","description":null,"archived":false,"fork":false,"pushed_at":"2025-03-19T12:18:40.000Z","size":23,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-19T13:27:14.937Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/snickerjp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"publiccode":null,"codemeta":null}},"created_at":"2025-03-19T12:12:30.000Z","updated_at":"2025-03-19T12:18:44.000Z","dependencies_parsed_at":"2025-03-21T03:15:24.519Z","dependency_job_id":null,"html_url":"https://github.com/snickerjp/lifecycle-manager","commit_stats":null,"previous_names":["snickerjp/lifecycle-manager"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snickerjp%2Flifecycle-manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snickerjp%2Flifecycle-manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snickerjp%2Flifecycle-manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/snickerjp%2Flifecycle-manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/snickerjp","download_url":"https://codeload.github.com/snickerjp/lifecycle-manager/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245223206,"owners_count":20580315,"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":[],"created_at":"2025-03-24T06:33:05.852Z","updated_at":"2025-03-24T06:33:58.521Z","avatar_url":"https://github.com/snickerjp.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# End of Life (EoL) \u0026 Maintenance Deadline Management System\n\n## **概要**\n\n自社使用製品の End of Life (EoL) や定期的な保守期限を管理するシステムを開発する。\n\n## **要件**\n\n### **ユーザー管理**\n\n- IdP として Okta を利用する。\n- 認証機能は Okta に依存しない形とし、OpenID Connect（OIDC）および SAML をサポートする。\n- ロール管理は実装しない。\n- どのユーザーがどの製品を登録したかをログに記録する。\n\n### **製品管理**\n\n- 製品の登録、編集、削除、一覧表示。\n- OS、ミドルウェア（DB、プログラミング言語、フレームワーク）、ネットワーク機器などの種別ごとに管理。\n- 1つの製品が複数のカテゴリ（DEVELOPMENT、Operation など）に紐づけ可能。\n- カテゴリの登録、編集、削除が可能。\n\n### **EoL \u0026 保守期限管理**\n\n- 製品と EoL は 1:1 の関係。\n- OS・ミドルウェアの EoL 情報を `https://endoflife.date/` から API で取得。\n  - 取得先の例:\n    - Oracle JDK: `https://endoflife.date/api/oracle-jdk.json`\n    - CentOS: `https://endoflife.date/api/centos.json`\n  - 更新頻度は 1 日 1 回。\n  - 更新エラー時はエラーログを出力し、前回のデータを保持。\n  - 更新のリトライは翌日の実行時に行う。\n- 定期的な保守期限（例: サポート契約の期限）も管理対象とする。\n\n### **ダッシュボード**\n\n- 製品ごとの EoL 情報を一覧表示。\n- カテゴリごとのフィルター機能（DEVELOPMENT、Operation）。\n\n### **通知機能**\n\n- EoL が近づいたら通知を送信。\n- メール（SendGrid）と Slack 通知。\n- 通知タイミングは 1 ヶ月前をデフォルトとし、カスタマイズ可能。\n- 通知頻度: 1 ヶ月前、2 週間前、1 週間前、3 日前、1 日前。\n- 通知履歴は DB ではなくログファイルに保存。\n\n### **ログ機能**\n\n- ユーザーの操作ログを記録（ユーザーID、操作内容、日時）。\n\n### **CSV インポート / エクスポート**\n\n- **エクスポート**: 製品・EoL 情報を CSV 形式で出力。\n- **インポート**:\n  - UTF-8 エンコード。\n  - 製品情報（製品名、取引先会社（空欄可）、EoL 日）。\n  - 日付フォーマットエラーはエラーとして表示。\n  - 重複データは差分を比較し、ユーザーが選択可能。\n  - CSV の差分比較 UI を提供（ハイライト付き）。\n\n## **技術要件**\n\n- **フロントエンド**: React, TypeScript, Material-UI\n- **バックエンド**: FastAPI (Python)\n- **データベース**: 初期は SQLite、運用では MySQL\n- **非同期処理**: Celery + Redis（Job の WebUI は Flower）\n- **スキーマ管理**: Atlas (`https://atlasgo.io/`)\n- **キャッシュ**: Redis\n- **CI/CD**: GitHub Actions\n- **テスト**:\n  - Jest, React Testing Library\n  - MySQL のテストは Docker を利用\n- **開発環境**:\n  - Docker, Docker Compose\n  - `docker-compose.yml` を `compose.yaml` に移行\n  - MySQL も Docker で立ち上げ\n- **Python パッケージ管理**: Poetry\n\n## **データベース設計（HCL形式）**\n\n```hcl\ntable \"products\" {\n  schema = schema.public\n  column \"id\" {\n    null = false\n    type = int\n    auto_increment = true\n  }\n  column \"name\" {\n    null = false\n    type = varchar(255)\n  }\n  column \"vendor\" {\n    null = true\n    type = varchar(255)\n  }\n  column \"category_id\" {\n    null = false\n    type = int\n  }\n  primary_key {\n    columns = [column.id]\n  }\n  foreign_key \"fk_category\" {\n    columns     = [column.category_id]\n    ref_columns = [table.categories.column.id]\n  }\n}\n\ntable \"eol\" {\n  schema = schema.public\n  column \"id\" {\n    null = false\n    type = int\n    auto_increment = true\n  }\n  column \"product_id\" {\n    null = false\n    type = int\n  }\n  column \"eol_date\" {\n    null = false\n    type = date\n  }\n  primary_key {\n    columns = [column.id]\n  }\n  foreign_key \"fk_product\" {\n    columns     = [column.product_id]\n    ref_columns = [table.products.column.id]\n  }\n}\n```\n\n## **API 設計（OpenAPI 準拠）**\n\n```yaml\nopenapi: 3.0.0\ninfo:\n  title: Lifecycle Manager API\n  version: 1.0.0\npaths:\n  /products:\n    get:\n      summary: 製品一覧を取得\n      responses:\n        '200':\n          description: 成功\n    post:\n      summary: 製品を登録\n      responses:\n        '201':\n          description: 製品登録成功\n  /products/{id}:\n    get:\n      summary: 特定の製品情報を取得\n      responses:\n        '200':\n          description: 成功\n    put:\n      summary: 製品情報を更新\n      responses:\n        '200':\n          description: 更新成功\n    delete:\n      summary: 製品を削除\n      responses:\n        '204':\n          description: 削除成功\n  /eol:\n    get:\n      summary: EoL 情報を取得\n      responses:\n        '200':\n          description: 成功\n    post:\n      summary: EoL を登録\n      responses:\n        '201':\n          description: 登録成功\n```\n\n## **リポジトリ名**\n\n- `lifecycle-manager` (採用)\n- その他候補: `eol-tracker`, `maint-lifecycle`, `product-lifecycle`\n\n## **今後のステップ**\n\n1. バックエンド実装のディレクトリ構成を決定\n2. FastAPI + Celery + Redis の環境構築\n3. フロントエンドの基本 UI 作成\n4. API 実装とテスト\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnickerjp%2Flifecycle-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsnickerjp%2Flifecycle-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsnickerjp%2Flifecycle-manager/lists"}