yjcli 0.1.4__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {yjcli-0.1.4 → yjcli-0.2.1}/PKG-INFO +18 -11
- {yjcli-0.1.4 → yjcli-0.2.1}/README.md +17 -10
- {yjcli-0.1.4 → yjcli-0.2.1}/pyproject.toml +1 -1
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-arch-core/SKILL.md +15 -6
- yjcli-0.2.1/src/yjcli/data/skills/yj-scheduler/SKILL.md +124 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/AGENTS.md +14 -1
- yjcli-0.2.1/src/yjcli/data/templates/Diff.md +9 -0
- yjcli-0.2.1/src/yjcli/data/templates/Makefile +47 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/make.bat +23 -3
- yjcli-0.2.1/src/yjcli/data/templates/platform/scripts/deploy-common.bat +33 -0
- yjcli-0.2.1/src/yjcli/data/templates/platform/scripts/deploy-common.sh +35 -0
- yjcli-0.2.1/src/yjcli/data/templates/platform/scripts/deploy-development.bat +21 -0
- yjcli-0.2.1/src/yjcli/data/templates/platform/scripts/deploy-development.sh +20 -0
- yjcli-0.2.1/src/yjcli/data/templates/platform/scripts/deploy-production.bat +21 -0
- yjcli-0.2.1/src/yjcli/data/templates/platform/scripts/deploy-production.sh +20 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/modules/constants.py +2 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/services/scaffold.py +29 -9
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/services/sync.py +33 -12
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/services/wiring.py +7 -1
- yjcli-0.1.4/src/yjcli/data/templates/Makefile +0 -34
- {yjcli-0.1.4 → yjcli-0.2.1}/.gitignore +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/LICENSE +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/__init__.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/__main__.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/cli.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/commands/__init__.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/commands/init_cmd.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/commands/platform.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/commands/service.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/commands/sync.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/__init__.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-backend-msa/SKILL.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-backend-service/SKILL.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-browser-extension/SKILL.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-cli/SKILL.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-frontend/SKILL.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-mobile-app/SKILL.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/skills/yj-pc-app/SKILL.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/.gitignore +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/TOOLS.md +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/app/.env.development +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/app/.env.examples +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/app/.env.local-dev +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/app/.env.production +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/listen/.env.development +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/listen/.env.examples +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/listen/.env.local-dev +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/listen/.env.production +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/worker/.env.development +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/worker/.env.examples +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/worker/.env.local-dev +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/envs/worker/.env.production +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/frontend/package.json +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/frontend/vite.config.ts +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/scripts/run.bat +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/platform/scripts/run.sh +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/data/templates/settings.json +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/modules/__init__.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/modules/fsutil.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/modules/paths.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/modules/prompt.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/services/__init__.py +0 -0
- {yjcli-0.1.4 → yjcli-0.2.1}/src/yjcli/services/status.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: yjcli
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Scaffold platforms, services, and AI agent wiring (Cursor/Claude/Codex) for YJ architecture repos.
|
|
5
5
|
Project-URL: Homepage, https://github.com/yseiren87/yjcli
|
|
6
6
|
Project-URL: Repository, https://github.com/yseiren87/yjcli
|
|
@@ -68,7 +68,7 @@ make backend NAME=api # start one service
|
|
|
68
68
|
|
|
69
69
|
Use with `-t` / `--type` (repeatable on `init` / `platform add`):
|
|
70
70
|
|
|
71
|
-
`backend` · `backend-service` · `frontend` · `mobile-app` · `pc-app` · `cli` · `browser-extension`
|
|
71
|
+
`backend` · `backend-service` · `frontend` · `mobile-app` · `pc-app` · `cli` · `browser-extension` · `scheduler`
|
|
72
72
|
|
|
73
73
|
## What `init` creates
|
|
74
74
|
|
|
@@ -76,14 +76,17 @@ Use with `-t` / `--type` (repeatable on `init` / `platform add`):
|
|
|
76
76
|
- Skills under `.cursor/skills/`, `.claude/skills/`, `.agents/skills/` (Codex)
|
|
77
77
|
- Claude `settings.json`
|
|
78
78
|
- Root `Makefile`, `make.bat`, `TOOLS.md`, `.gitignore`
|
|
79
|
-
-
|
|
79
|
+
- `Diff.md` — user-maintained architecture difference and manual restoration notes
|
|
80
|
+
- Selected platform roots with `scripts/run.*` and development/production deploy templates
|
|
80
81
|
|
|
81
|
-
The root `Makefile` / `make.bat`
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
82
|
+
The root `Makefile` / `make.bat` wires platform run and deploy entry points. Deploy
|
|
83
|
+
templates print the exact file to implement and fail until the project supplies
|
|
84
|
+
its build/package and upload logic. They remain platform-level; do not add
|
|
85
|
+
per-service `scripts/` directories or per-service Makefiles.
|
|
86
|
+
|
|
87
|
+
`Diff.md` is created only when missing, including with `init --force`. yjcli never
|
|
88
|
+
reads, updates, overwrites, or uses it for automatic restoration during sync or
|
|
89
|
+
migration.
|
|
87
90
|
|
|
88
91
|
Operating rules (skill routing, output discipline) are in `AGENTS.md` — not in
|
|
89
92
|
`.cursor/rules` / `.claude/rules`.
|
|
@@ -102,6 +105,8 @@ inferring npm, uv, Go, or another language/runtime from project manifests.
|
|
|
102
105
|
```bash
|
|
103
106
|
make <platform> # all services under that platform (concurrent)
|
|
104
107
|
make <platform> NAME=<service> # one service
|
|
108
|
+
make <platform>-deploy-development [NAME=<service>]
|
|
109
|
+
make <platform>-deploy-production [NAME=<service>]
|
|
105
110
|
make help
|
|
106
111
|
```
|
|
107
112
|
|
|
@@ -111,7 +116,7 @@ make help
|
|
|
111
116
|
|---------|------|
|
|
112
117
|
| `yjcli sync agents` | After editing `AGENTS.md` — refreshes `CLAUDE.md` |
|
|
113
118
|
| `yjcli sync skills` | Refresh packaged skills (Cursor / Claude / Codex) |
|
|
114
|
-
| `yjcli sync make` | Overwrite root
|
|
119
|
+
| `yjcli sync make` | Overwrite root make/run files; install missing deploy scripts while preserving implemented ones |
|
|
115
120
|
| `yjcli sync all` | Soft upgrade — mirror CLAUDE + skills + make (**keeps** your `AGENTS.md`) |
|
|
116
121
|
| `yjcli sync migrate -y` | **Hard** upgrade — package template overwrites `AGENTS.md`, wipes skills dirs, drops legacy rules/`.agent`, refreshes settings/TOOLS/gitignore/make |
|
|
117
122
|
|
|
@@ -127,7 +132,7 @@ Edit `AGENTS.md` only; do not edit `CLAUDE.md` by hand. Use `migrate` when upgra
|
|
|
127
132
|
|
|
128
133
|
## Notes
|
|
129
134
|
|
|
130
|
-
- `platform add`
|
|
135
|
+
- `platform add` creates platform roots and their run/deploy scripts (no services, skills, or root Makefile).
|
|
131
136
|
- `service add` needs the platform root first (`init` or `platform add`).
|
|
132
137
|
- Non-interactive: pass `-t` / `--all` / `-p` / `-n` as needed, and pass
|
|
133
138
|
`--yes` for every `sync` command.
|
|
@@ -146,9 +151,11 @@ yjcli init --force
|
|
|
146
151
|
yjcli platform add
|
|
147
152
|
yjcli platform add --all
|
|
148
153
|
yjcli platform add -t cli
|
|
154
|
+
yjcli platform add -t scheduler
|
|
149
155
|
|
|
150
156
|
yjcli service add
|
|
151
157
|
yjcli service add -p backend -n api
|
|
158
|
+
yjcli service add -p scheduler -n operations
|
|
152
159
|
|
|
153
160
|
yjcli sync agents
|
|
154
161
|
yjcli sync skills
|
|
@@ -43,7 +43,7 @@ make backend NAME=api # start one service
|
|
|
43
43
|
|
|
44
44
|
Use with `-t` / `--type` (repeatable on `init` / `platform add`):
|
|
45
45
|
|
|
46
|
-
`backend` · `backend-service` · `frontend` · `mobile-app` · `pc-app` · `cli` · `browser-extension`
|
|
46
|
+
`backend` · `backend-service` · `frontend` · `mobile-app` · `pc-app` · `cli` · `browser-extension` · `scheduler`
|
|
47
47
|
|
|
48
48
|
## What `init` creates
|
|
49
49
|
|
|
@@ -51,14 +51,17 @@ Use with `-t` / `--type` (repeatable on `init` / `platform add`):
|
|
|
51
51
|
- Skills under `.cursor/skills/`, `.claude/skills/`, `.agents/skills/` (Codex)
|
|
52
52
|
- Claude `settings.json`
|
|
53
53
|
- Root `Makefile`, `make.bat`, `TOOLS.md`, `.gitignore`
|
|
54
|
-
-
|
|
54
|
+
- `Diff.md` — user-maintained architecture difference and manual restoration notes
|
|
55
|
+
- Selected platform roots with `scripts/run.*` and development/production deploy templates
|
|
55
56
|
|
|
56
|
-
The root `Makefile` / `make.bat`
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
The root `Makefile` / `make.bat` wires platform run and deploy entry points. Deploy
|
|
58
|
+
templates print the exact file to implement and fail until the project supplies
|
|
59
|
+
its build/package and upload logic. They remain platform-level; do not add
|
|
60
|
+
per-service `scripts/` directories or per-service Makefiles.
|
|
61
|
+
|
|
62
|
+
`Diff.md` is created only when missing, including with `init --force`. yjcli never
|
|
63
|
+
reads, updates, overwrites, or uses it for automatic restoration during sync or
|
|
64
|
+
migration.
|
|
62
65
|
|
|
63
66
|
Operating rules (skill routing, output discipline) are in `AGENTS.md` — not in
|
|
64
67
|
`.cursor/rules` / `.claude/rules`.
|
|
@@ -77,6 +80,8 @@ inferring npm, uv, Go, or another language/runtime from project manifests.
|
|
|
77
80
|
```bash
|
|
78
81
|
make <platform> # all services under that platform (concurrent)
|
|
79
82
|
make <platform> NAME=<service> # one service
|
|
83
|
+
make <platform>-deploy-development [NAME=<service>]
|
|
84
|
+
make <platform>-deploy-production [NAME=<service>]
|
|
80
85
|
make help
|
|
81
86
|
```
|
|
82
87
|
|
|
@@ -86,7 +91,7 @@ make help
|
|
|
86
91
|
|---------|------|
|
|
87
92
|
| `yjcli sync agents` | After editing `AGENTS.md` — refreshes `CLAUDE.md` |
|
|
88
93
|
| `yjcli sync skills` | Refresh packaged skills (Cursor / Claude / Codex) |
|
|
89
|
-
| `yjcli sync make` | Overwrite root
|
|
94
|
+
| `yjcli sync make` | Overwrite root make/run files; install missing deploy scripts while preserving implemented ones |
|
|
90
95
|
| `yjcli sync all` | Soft upgrade — mirror CLAUDE + skills + make (**keeps** your `AGENTS.md`) |
|
|
91
96
|
| `yjcli sync migrate -y` | **Hard** upgrade — package template overwrites `AGENTS.md`, wipes skills dirs, drops legacy rules/`.agent`, refreshes settings/TOOLS/gitignore/make |
|
|
92
97
|
|
|
@@ -102,7 +107,7 @@ Edit `AGENTS.md` only; do not edit `CLAUDE.md` by hand. Use `migrate` when upgra
|
|
|
102
107
|
|
|
103
108
|
## Notes
|
|
104
109
|
|
|
105
|
-
- `platform add`
|
|
110
|
+
- `platform add` creates platform roots and their run/deploy scripts (no services, skills, or root Makefile).
|
|
106
111
|
- `service add` needs the platform root first (`init` or `platform add`).
|
|
107
112
|
- Non-interactive: pass `-t` / `--all` / `-p` / `-n` as needed, and pass
|
|
108
113
|
`--yes` for every `sync` command.
|
|
@@ -121,9 +126,11 @@ yjcli init --force
|
|
|
121
126
|
yjcli platform add
|
|
122
127
|
yjcli platform add --all
|
|
123
128
|
yjcli platform add -t cli
|
|
129
|
+
yjcli platform add -t scheduler
|
|
124
130
|
|
|
125
131
|
yjcli service add
|
|
126
132
|
yjcli service add -p backend -n api
|
|
133
|
+
yjcli service add -p scheduler -n operations
|
|
127
134
|
|
|
128
135
|
yjcli sync agents
|
|
129
136
|
yjcli sync skills
|
|
@@ -30,11 +30,12 @@ mobile-app/ # yj-mobile-app
|
|
|
30
30
|
pc-app/ # yj-pc-app
|
|
31
31
|
cli/ # yj-cli
|
|
32
32
|
browser-extension/ # yj-browser-extension
|
|
33
|
+
scheduler/ # yj-scheduler
|
|
33
34
|
```
|
|
34
35
|
|
|
35
36
|
```text
|
|
36
37
|
{platform}/
|
|
37
|
-
scripts/ # platform
|
|
38
|
+
scripts/ # platform run + deploy entry points
|
|
38
39
|
{service_name}/ # one deployable / one app
|
|
39
40
|
```
|
|
40
41
|
|
|
@@ -45,10 +46,17 @@ browser-extension/ # yj-browser-extension
|
|
|
45
46
|
`install`, or `help` targets. Do not add per-service `scripts/`.
|
|
46
47
|
Root `make <platform>` starts all services under that platform (concurrent); `NAME=<service>` runs one.
|
|
47
48
|
Platforms run via `*/scripts/run.*`; services are sibling dirs created with `yjcli service add`.
|
|
48
|
-
- The root `Makefile` / `make.bat`
|
|
49
|
-
`<platform
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
- The root `Makefile` / `make.bat` wires platform run and deploy commands. Use
|
|
50
|
+
`<platform>-deploy-development|production [NAME=<service>]` for deploys.
|
|
51
|
+
`deploy-common.*` owns shared build/package preparation; the environment-specific
|
|
52
|
+
deploy script calls it and then owns upload/rollout. Generated deploy scripts fail
|
|
53
|
+
with an implementation prompt until the repository replaces their guarded stubs.
|
|
54
|
+
- Deploy scripts are repository-owned after creation. `yjcli sync make` installs
|
|
55
|
+
missing deploy scripts but preserves existing ones.
|
|
56
|
+
- `Diff.md` is an optional, user-maintained reference for meaningful architecture
|
|
57
|
+
differences from yjcli defaults and their manual restoration notes. Update it
|
|
58
|
+
when that record would help, but never treat it as an automated sync, migration,
|
|
59
|
+
backup, comparison, or restoration mechanism. Never place secrets in it.
|
|
52
60
|
|
|
53
61
|
|
|
54
62
|
## Environment (guardrails only)
|
|
@@ -64,7 +72,7 @@ Required files at each service root (no plain `.env`):
|
|
|
64
72
|
`.env.local` convention unless a thin loader maps it to this structure.
|
|
65
73
|
- Env field sets come from `templates/platform/envs/<kind>/` via platform mapping (`listen` / `worker` / `app`).
|
|
66
74
|
- `listen`: `backend` (PORT 8080), `frontend` (PORT 5173)
|
|
67
|
-
- `worker`: `backend-service`, `browser-extension/native_
|
|
75
|
+
- `worker`: `backend-service`, `browser-extension/native_*`, `scheduler` (HOST/PORT optional)
|
|
68
76
|
- `app`: `cli`, `mobile-app`, `pc-app`, `browser-extension` (NAME/VERSION only)
|
|
69
77
|
Do not invent fields outside those templates; environment filenames remain
|
|
70
78
|
extensible through the `.env.<environment>` pattern above.
|
|
@@ -93,6 +101,7 @@ Required files at each service root (no plain `.env`):
|
|
|
93
101
|
| `cli/**` | `yj-cli` |
|
|
94
102
|
| `browser-extension/native_*/**` | `yj-backend-service` |
|
|
95
103
|
| `browser-extension/**` (other) | `yj-browser-extension` |
|
|
104
|
+
| `scheduler/**` | `yj-scheduler` |
|
|
96
105
|
|
|
97
106
|
Never load all platform skills. Never apply a platform skill outside its folder.
|
|
98
107
|
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: yj-scheduler
|
|
3
|
+
description: >-
|
|
4
|
+
Long-running scheduler architecture for multiple periodic batch jobs. Use
|
|
5
|
+
only when editing scheduler/**. Language-agnostic: use an established
|
|
6
|
+
scheduling framework from the project's ecosystem without prescribing a
|
|
7
|
+
specific library. Covers job registration, execution isolation, overlap,
|
|
8
|
+
misfires, timezones, retries, locks, observability, and graceful shutdown.
|
|
9
|
+
Do not use for backend/, backend-service/, frontend/, mobile-app/, pc-app/,
|
|
10
|
+
cli/, or browser-extension/.
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# yj-scheduler
|
|
14
|
+
|
|
15
|
+
Requires `yj-arch-core`. Scope: **`scheduler/` only**.
|
|
16
|
+
|
|
17
|
+
## Purpose
|
|
18
|
+
|
|
19
|
+
Run multiple recurring batch jobs in one or more long-running scheduler
|
|
20
|
+
processes. Use an established scheduling framework from the selected language
|
|
21
|
+
ecosystem. Choose the concrete framework from the repository's stack and
|
|
22
|
+
existing dependencies.
|
|
23
|
+
|
|
24
|
+
Do not implement cron parsing, durable scheduling, misfire handling, or a
|
|
25
|
+
`while` + `sleep` scheduling loop from scratch.
|
|
26
|
+
|
|
27
|
+
## Shape
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
scheduler/
|
|
31
|
+
scripts/ # platform-level only
|
|
32
|
+
{scheduler_name}/ # one deployable scheduler process
|
|
33
|
+
apps/ # entry: boot, registration, wiring, shutdown
|
|
34
|
+
services/
|
|
35
|
+
{job_name}/ # one batch workflow
|
|
36
|
+
domains/ # optional: owned concepts only
|
|
37
|
+
modules/ # scheduler adapter, db/api clients, lock, clock
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- One scheduler process may register multiple related jobs.
|
|
41
|
+
- Split jobs into separate `{scheduler_name}` deployables only when they need
|
|
42
|
+
independent deployment, scaling, dependencies, permissions, or failure isolation.
|
|
43
|
+
- Do not add per-job `scripts/` or Makefiles. Root `make scheduler` runs all
|
|
44
|
+
scheduler services; `NAME=<scheduler_name>` runs one.
|
|
45
|
+
- This is a long-running worker platform. `HOST` and `PORT` are optional and
|
|
46
|
+
should exist only when the process exposes a real endpoint.
|
|
47
|
+
|
|
48
|
+
## Roles
|
|
49
|
+
|
|
50
|
+
### entry (`apps`)
|
|
51
|
+
|
|
52
|
+
- Create and configure the scheduling framework, register triggers, wire job
|
|
53
|
+
handlers, start the process, and perform graceful shutdown.
|
|
54
|
+
- Keep registration declarative and discoverable in one entry area.
|
|
55
|
+
- Framework callbacks must be thin: add execution context, call one flow, and
|
|
56
|
+
report its result. No query, transformation, or persistence logic in callbacks.
|
|
57
|
+
|
|
58
|
+
### flow (`services/{job_name}`)
|
|
59
|
+
|
|
60
|
+
- Each periodic job is an independently testable workflow.
|
|
61
|
+
- Own job-specific input, orchestration, batching, checkpointing, and result shape.
|
|
62
|
+
- A failure in one job must not terminate or block unrelated jobs.
|
|
63
|
+
- Make operations idempotent whenever a retry or duplicate trigger is possible.
|
|
64
|
+
|
|
65
|
+
### domain / infra
|
|
66
|
+
|
|
67
|
+
- Add `domains/` only for concepts or shared policy owned by this process;
|
|
68
|
+
persistence is not required. Do not create a domain merely because a job exists.
|
|
69
|
+
- Put framework integration, distributed locks, clocks, persistence, logging,
|
|
70
|
+
and external clients in `modules/`.
|
|
71
|
+
- Do not import another platform's source tree; communicate through explicit
|
|
72
|
+
APIs or generated contracts.
|
|
73
|
+
|
|
74
|
+
## Scheduling policy
|
|
75
|
+
|
|
76
|
+
For every job, make these decisions explicit near its registration or config:
|
|
77
|
+
|
|
78
|
+
- stable job identifier and handler
|
|
79
|
+
- periodic or calendar trigger and explicit timezone
|
|
80
|
+
- whether overlapping executions are allowed
|
|
81
|
+
- misfire behavior (skip, coalesce, or catch up)
|
|
82
|
+
- timeout, retry, and backoff behavior
|
|
83
|
+
- concurrency limit and multi-instance ownership/locking strategy
|
|
84
|
+
|
|
85
|
+
Never rely implicitly on the host's local timezone. Do not scatter schedule
|
|
86
|
+
expressions across callbacks. Fixed business schedules may live in typed code or
|
|
87
|
+
project configuration; expose them as environment-specific settings only when
|
|
88
|
+
deployments genuinely need different schedules.
|
|
89
|
+
|
|
90
|
+
When more than one scheduler instance can run, use the framework's persistent
|
|
91
|
+
job store/single-run facility or a distributed lock. A process-local mutex does
|
|
92
|
+
not prevent duplicate execution across instances.
|
|
93
|
+
|
|
94
|
+
## Reliability and observability
|
|
95
|
+
|
|
96
|
+
- Log job id, execution/run id, scheduled time, actual start, completion or
|
|
97
|
+
failure, duration, and retry attempt using structured fields.
|
|
98
|
+
- Define shutdown behavior: stop accepting triggers, then finish or safely
|
|
99
|
+
cancel active jobs within a bounded grace period.
|
|
100
|
+
- Long-running or high-volume jobs should use bounded batches and checkpoints so
|
|
101
|
+
they can resume safely after interruption.
|
|
102
|
+
- Keep retry scope narrow. Do not retry permanent validation or authorization
|
|
103
|
+
failures as though they were transient infrastructure failures.
|
|
104
|
+
- Inject or wrap the clock in flow/domain tests; do not make business rules
|
|
105
|
+
depend directly on wall-clock calls throughout the codebase.
|
|
106
|
+
|
|
107
|
+
## Import direction
|
|
108
|
+
|
|
109
|
+
```text
|
|
110
|
+
entry/framework callback -> flow -> domain? -> infra
|
|
111
|
+
entry -> infra
|
|
112
|
+
flow -> infra
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Forbidden: business logic in trigger callbacks; flow importing entry/framework
|
|
116
|
+
bootstrap; domain importing scheduler framework types; jobs calling one another
|
|
117
|
+
for sequencing when a single coordinating flow owns the workflow.
|
|
118
|
+
|
|
119
|
+
## Editing scope
|
|
120
|
+
|
|
121
|
+
- Stay within `scheduler/{scheduler_name}/` unless the task explicitly changes
|
|
122
|
+
shared contracts or platform wiring.
|
|
123
|
+
- Prefer extending an existing scheduler process for related jobs; do not create
|
|
124
|
+
one deployable per cron expression automatically.
|
|
@@ -29,6 +29,7 @@ When creating, modifying, reviewing, or refactoring code:
|
|
|
29
29
|
| `cli/**` | `yj-cli` |
|
|
30
30
|
| `browser-extension/native_*/**` | `yj-backend-service` |
|
|
31
31
|
| `browser-extension/**` (other) | `yj-browser-extension` |
|
|
32
|
+
| `scheduler/**` | `yj-scheduler` |
|
|
32
33
|
|
|
33
34
|
Never load all platform skills. Never apply a platform skill outside its folder.
|
|
34
35
|
|
|
@@ -57,8 +58,12 @@ Paths from `yjcli init` are fixed; add platform/app rows with `<path>` / `<role>
|
|
|
57
58
|
| `AGENTS.md` | Agent / contributor guide (this file) — source of truth |
|
|
58
59
|
| `CLAUDE.md` | Mirror of `AGENTS.md` — do not edit; refresh with `yjcli sync agents` |
|
|
59
60
|
| `TOOLS.md` | Release-tools feature spec (version / deploy / git) |
|
|
60
|
-
| `
|
|
61
|
+
| `Diff.md` | User-maintained reference for project differences from yjcli defaults; yjcli never updates or restores from it |
|
|
62
|
+
| `Makefile` | Root entry — run via `make <platform>`; deploy via `<platform>-deploy-development\|production`, optionally with `NAME=<service>` |
|
|
61
63
|
| `make.bat` | Extensible Windows counterpart of root Makefile |
|
|
64
|
+
| `<platform>/scripts/deploy-common.*` | Repository-owned shared build/package implementation |
|
|
65
|
+
| `<platform>/scripts/deploy-development.*` | Repository-owned development upload/deploy implementation |
|
|
66
|
+
| `<platform>/scripts/deploy-production.*` | Repository-owned production upload/deploy implementation |
|
|
62
67
|
| `.gitignore` | Canonical ignore rules |
|
|
63
68
|
| `.cursor/skills/` | Cursor skills (copied from package) |
|
|
64
69
|
| `.claude/skills/` | Claude skills (copied from package) |
|
|
@@ -93,6 +98,10 @@ Paths from `yjcli init` are fixed; add platform/app rows with `<path>` / `<role>
|
|
|
93
98
|
|
|
94
99
|
# build
|
|
95
100
|
<command>
|
|
101
|
+
|
|
102
|
+
# deploy (generated stubs fail until implemented)
|
|
103
|
+
make <platform>-deploy-development [NAME=<service>]
|
|
104
|
+
make <platform>-deploy-production [NAME=<service>]
|
|
96
105
|
```
|
|
97
106
|
|
|
98
107
|
---
|
|
@@ -129,10 +138,13 @@ Paths from `yjcli init` are fixed; add platform/app rows with `<path>` / `<role>
|
|
|
129
138
|
### Do
|
|
130
139
|
|
|
131
140
|
- `<item>`
|
|
141
|
+
- Record meaningful architecture differences from yjcli defaults in `Diff.md` when useful for manual restoration.
|
|
132
142
|
|
|
133
143
|
### Don't
|
|
134
144
|
|
|
135
145
|
- `<item>`
|
|
146
|
+
- Do not expect `Diff.md` to drive sync, migration, comparison, backup, or automatic restoration.
|
|
147
|
+
- Do not put secrets in `Diff.md`.
|
|
136
148
|
|
|
137
149
|
---
|
|
138
150
|
|
|
@@ -157,5 +169,6 @@ Paths from `yjcli init` are fixed; add platform/app rows with `<path>` / `<role>
|
|
|
157
169
|
| Kind | Location |
|
|
158
170
|
|------|----------|
|
|
159
171
|
| Release tools spec | `TOOLS.md` |
|
|
172
|
+
| Architecture differences | `Diff.md` |
|
|
160
173
|
| Packaged skills (source) | installed via `yjcli` → `.cursor` / `.claude` / `.agents` skills |
|
|
161
174
|
| `<kind>` | `<path>` |
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# 아키텍처 차이점
|
|
2
|
+
|
|
3
|
+
이 문서는 yjcli가 제공하는 기본 아키텍처와 현재 프로젝트 사이의 차이점을 기록하는 참고 자료다.
|
|
4
|
+
|
|
5
|
+
템플릿이나 에이전트 연결 파일이 갱신된 뒤 프로젝트 고유의 변경 사항을 사용자가 직접 확인하고 복원할 때 활용한다.
|
|
6
|
+
|
|
7
|
+
yjcli는 이 파일이 없을 때만 최초 생성하며, 이후에는 읽거나 수정하거나 덮어쓰지 않는다. 이 문서의 내용을 이용한 자동 비교, 백업 또는 복원도 수행하지 않는다.
|
|
8
|
+
|
|
9
|
+
비밀번호, 토큰, 인증정보 등 시크릿은 기록하지 않는다.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Platform targets are discovered from */scripts/run.sh (after yjcli platform add).
|
|
2
|
+
# Usage:
|
|
3
|
+
# make <platform> # all services under that platform (concurrent)
|
|
4
|
+
# make <platform> NAME=<service> # one service
|
|
5
|
+
# Deploy templates are platform-owned extension points. They intentionally fail
|
|
6
|
+
# until the repository implements the printed build/package/upload steps.
|
|
7
|
+
|
|
8
|
+
PLATFORMS := $(patsubst %/scripts/run.sh,%,$(wildcard */scripts/run.sh))
|
|
9
|
+
DEPLOY_DEVELOPMENT_TARGETS := $(addsuffix -deploy-development,$(PLATFORMS))
|
|
10
|
+
DEPLOY_PRODUCTION_TARGETS := $(addsuffix -deploy-production,$(PLATFORMS))
|
|
11
|
+
|
|
12
|
+
.PHONY: help $(PLATFORMS) $(DEPLOY_DEVELOPMENT_TARGETS) $(DEPLOY_PRODUCTION_TARGETS)
|
|
13
|
+
|
|
14
|
+
help:
|
|
15
|
+
@echo "Usage:"
|
|
16
|
+
@echo " make <platform> # start all services concurrently"
|
|
17
|
+
@echo " make <platform> NAME=<service> # start one service"
|
|
18
|
+
@echo " make <platform>-deploy-development [NAME=<service>]"
|
|
19
|
+
@echo " make <platform>-deploy-production [NAME=<service>]"
|
|
20
|
+
@echo ""
|
|
21
|
+
@echo "Available platforms (dirs with scripts/run.sh):"
|
|
22
|
+
@if [ -z "$(PLATFORMS)" ]; then \
|
|
23
|
+
echo " (none — run: yjcli platform add)"; \
|
|
24
|
+
else \
|
|
25
|
+
for p in $(PLATFORMS); do echo " $$p"; done; \
|
|
26
|
+
fi
|
|
27
|
+
@echo ""
|
|
28
|
+
@echo "Example: make backend"
|
|
29
|
+
@echo " make backend NAME=api"
|
|
30
|
+
@echo " make backend-deploy-development NAME=api"
|
|
31
|
+
@echo " make backend-deploy-production NAME=api"
|
|
32
|
+
|
|
33
|
+
$(PLATFORMS):
|
|
34
|
+
@test -x "$@/scripts/run.sh" || (echo "missing: $@/scripts/run.sh"; exit 1)
|
|
35
|
+
@if [ -n "$(NAME)" ]; then \
|
|
36
|
+
"$@/scripts/run.sh" "$(NAME)" $(ARGS); \
|
|
37
|
+
else \
|
|
38
|
+
"$@/scripts/run.sh" $(ARGS); \
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
$(DEPLOY_DEVELOPMENT_TARGETS): %-deploy-development:
|
|
42
|
+
@test -x "$*/scripts/deploy-development.sh" || (echo "missing: $*/scripts/deploy-development.sh"; exit 1)
|
|
43
|
+
@"$*/scripts/deploy-development.sh" "$(NAME)" $(ARGS)
|
|
44
|
+
|
|
45
|
+
$(DEPLOY_PRODUCTION_TARGETS): %-deploy-production:
|
|
46
|
+
@test -x "$*/scripts/deploy-production.sh" || (echo "missing: $*/scripts/deploy-production.sh"; exit 1)
|
|
47
|
+
@"$*/scripts/deploy-production.sh" "$(NAME)" $(ARGS)
|
|
@@ -1,12 +1,24 @@
|
|
|
1
1
|
@echo off
|
|
2
2
|
setlocal EnableExtensions EnableDelayedExpansion
|
|
3
|
-
rem
|
|
4
|
-
rem for example: make.bat backend-deploy NAME=api. yjcli does not define them.
|
|
3
|
+
rem Deploy scripts intentionally fail until their printed implementation steps are completed.
|
|
5
4
|
|
|
6
5
|
if /I "%~1"=="" goto help
|
|
7
6
|
if /I "%~1"=="help" goto help
|
|
8
7
|
|
|
9
|
-
set "
|
|
8
|
+
set "TARGET=%~1"
|
|
9
|
+
set "PLATFORM=%TARGET:-deploy-development=%"
|
|
10
|
+
if /I not "%PLATFORM%"=="%TARGET%" (
|
|
11
|
+
set "DEPLOY_ENV=development"
|
|
12
|
+
goto parse_start
|
|
13
|
+
)
|
|
14
|
+
set "PLATFORM=%TARGET:-deploy-production=%"
|
|
15
|
+
if /I not "%PLATFORM%"=="%TARGET%" (
|
|
16
|
+
set "DEPLOY_ENV=production"
|
|
17
|
+
goto parse_start
|
|
18
|
+
)
|
|
19
|
+
set "PLATFORM=%TARGET%"
|
|
20
|
+
|
|
21
|
+
:parse_start
|
|
10
22
|
if not exist "%PLATFORM%\scripts\run.bat" (
|
|
11
23
|
echo Unknown target: %PLATFORM%
|
|
12
24
|
echo Expected: %PLATFORM%\scripts\run.bat ^(yjcli platform add^)
|
|
@@ -23,6 +35,10 @@ shift
|
|
|
23
35
|
goto parse
|
|
24
36
|
|
|
25
37
|
:run_exec
|
|
38
|
+
if defined DEPLOY_ENV (
|
|
39
|
+
call "%PLATFORM%\scripts\deploy-%DEPLOY_ENV%.bat" "%NAME%"
|
|
40
|
+
exit /b !ERRORLEVEL!
|
|
41
|
+
)
|
|
26
42
|
if "%NAME%"=="" (
|
|
27
43
|
call "%PLATFORM%\scripts\run.bat"
|
|
28
44
|
) else (
|
|
@@ -34,6 +50,8 @@ exit /b %ERRORLEVEL%
|
|
|
34
50
|
echo Usage:
|
|
35
51
|
echo make.bat ^<platform^> # all services ^(separate windows^)
|
|
36
52
|
echo make.bat ^<platform^> NAME=^<service^> # one service
|
|
53
|
+
echo make.bat ^<platform^>-deploy-development [NAME=^<service^>]
|
|
54
|
+
echo make.bat ^<platform^>-deploy-production [NAME=^<service^>]
|
|
37
55
|
echo.
|
|
38
56
|
echo Available platforms (dirs with scripts\run.bat):
|
|
39
57
|
set "FOUND="
|
|
@@ -47,4 +65,6 @@ if not defined FOUND echo ^(none — run: yjcli platform add^)
|
|
|
47
65
|
echo.
|
|
48
66
|
echo Example: make.bat backend
|
|
49
67
|
echo make.bat backend NAME=api
|
|
68
|
+
echo make.bat backend-deploy-development NAME=api
|
|
69
|
+
echo make.bat backend-deploy-production NAME=api
|
|
50
70
|
exit /b 0
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
setlocal EnableExtensions
|
|
3
|
+
rem Shared build/package preparation for development and production deploys.
|
|
4
|
+
rem Replace the implementation guard below with repository-specific commands.
|
|
5
|
+
|
|
6
|
+
set "SCRIPT_DIR=%~dp0"
|
|
7
|
+
for %%D in ("%SCRIPT_DIR%..") do set "PLATFORM_DIR=%%~fD"
|
|
8
|
+
set "ENVIRONMENT=%~1"
|
|
9
|
+
set "NAME=%~2"
|
|
10
|
+
|
|
11
|
+
if /I not "%ENVIRONMENT%"=="development" if /I not "%ENVIRONMENT%"=="production" (
|
|
12
|
+
echo usage: %~nx0 ^<development^|production^> [service] [args...]
|
|
13
|
+
exit /b 1
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
if defined NAME if not exist "%PLATFORM_DIR%\%NAME%\" (
|
|
17
|
+
echo unknown service: %NAME% ^(expected %PLATFORM_DIR%\%NAME%^)
|
|
18
|
+
exit /b 1
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
for %%D in ("%PLATFORM_DIR%") do set "PLATFORM_NAME=%%~nxD"
|
|
22
|
+
echo [deploy] platform: %PLATFORM_NAME%
|
|
23
|
+
echo [deploy] environment: %ENVIRONMENT%
|
|
24
|
+
if defined NAME (echo [deploy] service: %NAME%) else echo [deploy] service: all
|
|
25
|
+
echo deploy common is not implemented.
|
|
26
|
+
echo Implement build/package logic in: %SCRIPT_DIR%deploy-common.bat
|
|
27
|
+
echo Examples: docker build, archive creation, frontend build
|
|
28
|
+
|
|
29
|
+
rem Implementation examples:
|
|
30
|
+
rem docker build -t "example/%NAME%:%ENVIRONMENT%" "%PLATFORM_DIR%"
|
|
31
|
+
rem tar -a -c -f "%NAME%.zip" -C "%PLATFORM_DIR%" "%NAME%"
|
|
32
|
+
rem cd /d "%PLATFORM_DIR%\%NAME%" ^&^& npm ci ^&^& npm run build
|
|
33
|
+
exit /b 1
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Shared build/package preparation for development and production deploys.
|
|
3
|
+
# Replace the implementation guard below with repository-specific commands.
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
7
|
+
PLATFORM_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
8
|
+
ENVIRONMENT="${1:-}"
|
|
9
|
+
NAME="${2:-}"
|
|
10
|
+
|
|
11
|
+
case "$ENVIRONMENT" in
|
|
12
|
+
development|production) ;;
|
|
13
|
+
*)
|
|
14
|
+
echo "usage: $0 <development|production> [service] [args...]"
|
|
15
|
+
exit 1
|
|
16
|
+
;;
|
|
17
|
+
esac
|
|
18
|
+
|
|
19
|
+
if [ -n "$NAME" ] && [ ! -d "$PLATFORM_DIR/$NAME" ]; then
|
|
20
|
+
echo "unknown service: $NAME (expected $PLATFORM_DIR/$NAME)"
|
|
21
|
+
exit 1
|
|
22
|
+
fi
|
|
23
|
+
|
|
24
|
+
echo "[deploy] platform: $(basename "$PLATFORM_DIR")"
|
|
25
|
+
echo "[deploy] environment: $ENVIRONMENT"
|
|
26
|
+
echo "[deploy] service: ${NAME:-all}"
|
|
27
|
+
echo "deploy common is not implemented."
|
|
28
|
+
echo "Implement build/package logic in: $SCRIPT_DIR/deploy-common.sh"
|
|
29
|
+
echo "Examples: docker build, archive creation, frontend build"
|
|
30
|
+
|
|
31
|
+
# Implementation examples:
|
|
32
|
+
# docker build -t "example/${NAME:-platform}:$ENVIRONMENT" "$PLATFORM_DIR"
|
|
33
|
+
# tar -czf "${NAME:-platform}.tar.gz" -C "$PLATFORM_DIR" "${NAME:-.}"
|
|
34
|
+
# (cd "$PLATFORM_DIR/$NAME" && npm ci && npm run build)
|
|
35
|
+
exit 1
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
setlocal EnableExtensions
|
|
3
|
+
rem Development deployment entry point. Keep shared preparation in deploy-common.bat.
|
|
4
|
+
|
|
5
|
+
set "SCRIPT_DIR=%~dp0"
|
|
6
|
+
set "NAME=%~1"
|
|
7
|
+
shift
|
|
8
|
+
|
|
9
|
+
call "%SCRIPT_DIR%deploy-common.bat" development "%NAME%" %*
|
|
10
|
+
if errorlevel 1 exit /b %ERRORLEVEL%
|
|
11
|
+
|
|
12
|
+
echo development upload is not implemented.
|
|
13
|
+
echo Implement upload/deploy logic in: %SCRIPT_DIR%deploy-development.bat
|
|
14
|
+
echo Examples: docker push, scp, S3 upload, kubectl apply
|
|
15
|
+
|
|
16
|
+
rem Development upload examples:
|
|
17
|
+
rem docker push "registry.example.com/%NAME%:development"
|
|
18
|
+
rem scp "%ARTIFACT%" "dev-server:/srv/%NAME%/"
|
|
19
|
+
rem aws s3 sync "%DIST_DIR%" "s3://example-development/%NAME%/"
|
|
20
|
+
rem kubectl apply -k deploy/overlays/development
|
|
21
|
+
exit /b 1
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Development deployment entry point. Keep shared preparation in deploy-common.sh.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
6
|
+
NAME="${1:-}"
|
|
7
|
+
shift || true
|
|
8
|
+
|
|
9
|
+
"$SCRIPT_DIR/deploy-common.sh" development "$NAME" "$@"
|
|
10
|
+
|
|
11
|
+
echo "development upload is not implemented."
|
|
12
|
+
echo "Implement upload/deploy logic in: $SCRIPT_DIR/deploy-development.sh"
|
|
13
|
+
echo "Examples: docker push, scp, S3 upload, kubectl apply"
|
|
14
|
+
|
|
15
|
+
# Development upload examples:
|
|
16
|
+
# docker push "registry.example.com/$NAME:development"
|
|
17
|
+
# scp "$ARTIFACT" "dev-server:/srv/$NAME/"
|
|
18
|
+
# aws s3 sync "$DIST_DIR" "s3://example-development/$NAME/"
|
|
19
|
+
# kubectl apply -k deploy/overlays/development
|
|
20
|
+
exit 1
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
@echo off
|
|
2
|
+
setlocal EnableExtensions
|
|
3
|
+
rem Production deployment entry point. Keep shared preparation in deploy-common.bat.
|
|
4
|
+
|
|
5
|
+
set "SCRIPT_DIR=%~dp0"
|
|
6
|
+
set "NAME=%~1"
|
|
7
|
+
shift
|
|
8
|
+
|
|
9
|
+
call "%SCRIPT_DIR%deploy-common.bat" production "%NAME%" %*
|
|
10
|
+
if errorlevel 1 exit /b %ERRORLEVEL%
|
|
11
|
+
|
|
12
|
+
echo production upload is not implemented.
|
|
13
|
+
echo Implement upload/deploy logic in: %SCRIPT_DIR%deploy-production.bat
|
|
14
|
+
echo Examples: registry push, production upload, release rollout
|
|
15
|
+
|
|
16
|
+
rem Recommended production steps:
|
|
17
|
+
rem - validate VERSION or release tag
|
|
18
|
+
rem - upload the artifact or push the container image
|
|
19
|
+
rem - deploy to production and run a health check
|
|
20
|
+
rem - roll back on failure
|
|
21
|
+
exit /b 1
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Production deployment entry point. Keep shared preparation in deploy-common.sh.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
6
|
+
NAME="${1:-}"
|
|
7
|
+
shift || true
|
|
8
|
+
|
|
9
|
+
"$SCRIPT_DIR/deploy-common.sh" production "$NAME" "$@"
|
|
10
|
+
|
|
11
|
+
echo "production upload is not implemented."
|
|
12
|
+
echo "Implement upload/deploy logic in: $SCRIPT_DIR/deploy-production.sh"
|
|
13
|
+
echo "Examples: registry push, production upload, release rollout"
|
|
14
|
+
|
|
15
|
+
# Recommended production steps:
|
|
16
|
+
# - validate VERSION or release tag
|
|
17
|
+
# - upload the artifact or push the container image
|
|
18
|
+
# - deploy to the production environment and run a health check
|
|
19
|
+
# - roll back on failure
|
|
20
|
+
exit 1
|
|
@@ -10,6 +10,7 @@ PLATFORMS: tuple[str, ...] = (
|
|
|
10
10
|
"pc-app",
|
|
11
11
|
"cli",
|
|
12
12
|
"browser-extension",
|
|
13
|
+
"scheduler",
|
|
13
14
|
)
|
|
14
15
|
|
|
15
16
|
RESERVED_SERVICE_NAMES: frozenset[str] = frozenset({"scripts", "proto"})
|
|
@@ -26,4 +27,5 @@ PLATFORM_ENV: dict[str, tuple[str, dict[str, str]]] = {
|
|
|
26
27
|
"mobile-app": ("app", {}),
|
|
27
28
|
"pc-app": ("app", {}),
|
|
28
29
|
"browser-extension": ("app", {}),
|
|
30
|
+
"scheduler": ("worker", {}),
|
|
29
31
|
}
|
|
@@ -28,6 +28,17 @@ _DEFAULT_ENV_FILE_NAMES = (
|
|
|
28
28
|
".env.examples",
|
|
29
29
|
)
|
|
30
30
|
|
|
31
|
+
_PLATFORM_SCRIPT_NAMES = (
|
|
32
|
+
"run.sh",
|
|
33
|
+
"run.bat",
|
|
34
|
+
"deploy-common.sh",
|
|
35
|
+
"deploy-common.bat",
|
|
36
|
+
"deploy-development.sh",
|
|
37
|
+
"deploy-development.bat",
|
|
38
|
+
"deploy-production.sh",
|
|
39
|
+
"deploy-production.bat",
|
|
40
|
+
)
|
|
41
|
+
|
|
31
42
|
|
|
32
43
|
def existing_platforms(root: Path) -> list[str]:
|
|
33
44
|
return [p for p in PLATFORMS if (root / p).is_dir()]
|
|
@@ -43,14 +54,21 @@ def create_platform(root: Path, platform: str) -> None:
|
|
|
43
54
|
scripts_dir.mkdir(parents=True, exist_ok=True)
|
|
44
55
|
|
|
45
56
|
templates = paths.templates_dir()
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
57
|
+
script_templates = templates / "platform" / "scripts"
|
|
58
|
+
missing = [
|
|
59
|
+
name
|
|
60
|
+
for name in _PLATFORM_SCRIPT_NAMES
|
|
61
|
+
if not (script_templates / name).is_file()
|
|
62
|
+
]
|
|
63
|
+
if missing:
|
|
64
|
+
abort(f"missing platform scripts under {script_templates}: {', '.join(missing)}")
|
|
65
|
+
|
|
66
|
+
for name in _PLATFORM_SCRIPT_NAMES:
|
|
67
|
+
source = script_templates / name
|
|
68
|
+
target = scripts_dir / name
|
|
69
|
+
shutil.copy2(source, target)
|
|
70
|
+
if name.endswith(".sh"):
|
|
71
|
+
target.chmod(target.stat().st_mode | 0o111)
|
|
54
72
|
|
|
55
73
|
if platform == "backend":
|
|
56
74
|
proto = dest / "proto"
|
|
@@ -122,7 +140,7 @@ def create_service(root: Path, platform: str, name: str) -> None:
|
|
|
122
140
|
_copy_env_templates(platform, name, base)
|
|
123
141
|
_copy_platform_extras(platform, name, base)
|
|
124
142
|
|
|
125
|
-
if platform in {"backend", "backend-service"}:
|
|
143
|
+
if platform in {"backend", "backend-service", "scheduler"}:
|
|
126
144
|
for sub in ("apps", "services", "domains", "modules"):
|
|
127
145
|
(base / sub).mkdir(exist_ok=True)
|
|
128
146
|
elif platform == "frontend":
|
|
@@ -242,3 +260,5 @@ def add_service_flow(
|
|
|
242
260
|
typer.echo(f"run all: make {chosen}")
|
|
243
261
|
typer.echo(f"run one: make {chosen} NAME={name}")
|
|
244
262
|
typer.echo(f" or: {chosen}/scripts/run.sh [{name}]")
|
|
263
|
+
typer.echo(f"deploy development: make {chosen}-deploy-development NAME={name}")
|
|
264
|
+
typer.echo(f"deploy production: make {chosen}-deploy-production NAME={name}")
|
|
@@ -76,7 +76,7 @@ def sync_skills(root: Path, *, force: bool = True) -> None:
|
|
|
76
76
|
|
|
77
77
|
|
|
78
78
|
def sync_make(root: Path, *, force: bool = True) -> None:
|
|
79
|
-
"""
|
|
79
|
+
"""Refresh managed make/run files and install missing deploy templates."""
|
|
80
80
|
templates = paths.templates_dir()
|
|
81
81
|
for name in ("Makefile", "make.bat"):
|
|
82
82
|
src = templates / name
|
|
@@ -85,10 +85,23 @@ def sync_make(root: Path, *, force: bool = True) -> None:
|
|
|
85
85
|
copy_file(src, root / name, force=force)
|
|
86
86
|
typer.echo("synced: packaged Makefile, make.bat -> repo root")
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
scripts_src = templates / "platform" / "scripts"
|
|
89
|
+
managed_names = ("run.sh", "run.bat")
|
|
90
|
+
deploy_names = (
|
|
91
|
+
"deploy-common.sh",
|
|
92
|
+
"deploy-common.bat",
|
|
93
|
+
"deploy-development.sh",
|
|
94
|
+
"deploy-development.bat",
|
|
95
|
+
"deploy-production.sh",
|
|
96
|
+
"deploy-production.bat",
|
|
97
|
+
)
|
|
98
|
+
missing = [
|
|
99
|
+
name
|
|
100
|
+
for name in (*managed_names, *deploy_names)
|
|
101
|
+
if not (scripts_src / name).is_file()
|
|
102
|
+
]
|
|
103
|
+
if missing:
|
|
104
|
+
abort(f"missing packaged platform scripts under {scripts_src}: {', '.join(missing)}")
|
|
92
105
|
|
|
93
106
|
installed = [p for p in PLATFORMS if (root / p).is_dir()]
|
|
94
107
|
if not installed:
|
|
@@ -98,13 +111,21 @@ def sync_make(root: Path, *, force: bool = True) -> None:
|
|
|
98
111
|
for platform in installed:
|
|
99
112
|
scripts_dir = root / platform / "scripts"
|
|
100
113
|
ensure_real_dir(scripts_dir)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
114
|
+
for name in managed_names:
|
|
115
|
+
copy_file(scripts_src / name, scripts_dir / name, force=force)
|
|
116
|
+
for name in deploy_names:
|
|
117
|
+
copy_file(scripts_src / name, scripts_dir / name, skip_existing=True)
|
|
118
|
+
executable_names = (
|
|
119
|
+
"run.sh",
|
|
120
|
+
"deploy-common.sh",
|
|
121
|
+
"deploy-development.sh",
|
|
122
|
+
"deploy-production.sh",
|
|
123
|
+
)
|
|
124
|
+
for name in executable_names:
|
|
125
|
+
target = scripts_dir / name
|
|
126
|
+
if target.is_file():
|
|
127
|
+
target.chmod(target.stat().st_mode | 0o111)
|
|
128
|
+
typer.echo(f"synced: {platform}/scripts (run refreshed; deploy preserved)")
|
|
108
129
|
|
|
109
130
|
|
|
110
131
|
def sync_all(root: Path, *, force: bool = True) -> None:
|
|
@@ -31,7 +31,7 @@ def ensure_agent_wiring(root: Path, *, force: bool = False) -> None:
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def ensure_root_from_templates(root: Path, *, force: bool = False) -> None:
|
|
34
|
-
"""Copy root
|
|
34
|
+
"""Copy managed root templates and create the user-owned Diff.md once."""
|
|
35
35
|
templates = paths.templates_dir()
|
|
36
36
|
for name in (".gitignore", "Makefile", "make.bat", "TOOLS.md"):
|
|
37
37
|
src = templates / name
|
|
@@ -39,3 +39,9 @@ def ensure_root_from_templates(root: Path, *, force: bool = False) -> None:
|
|
|
39
39
|
typer.echo(f"warn: missing template: {src}", err=True)
|
|
40
40
|
continue
|
|
41
41
|
copy_file(src, root / name, force=force)
|
|
42
|
+
|
|
43
|
+
diff_src = templates / "Diff.md"
|
|
44
|
+
if not diff_src.is_file():
|
|
45
|
+
typer.echo(f"warn: missing template: {diff_src}", err=True)
|
|
46
|
+
else:
|
|
47
|
+
copy_file(diff_src, root / "Diff.md", skip_existing=True)
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# Platform targets are discovered from */scripts/run.sh (after yjcli platform add).
|
|
2
|
-
# Usage:
|
|
3
|
-
# make <platform> # all services under that platform (concurrent)
|
|
4
|
-
# make <platform> NAME=<service> # one service
|
|
5
|
-
# Extend this root file for repository-owned work when needed. A useful pattern
|
|
6
|
-
# is <platform>-<action> with the same optional NAME selector, for example
|
|
7
|
-
# `make backend-deploy [NAME=api]`. yjcli does not define those actions.
|
|
8
|
-
|
|
9
|
-
PLATFORMS := $(patsubst %/scripts/run.sh,%,$(wildcard */scripts/run.sh))
|
|
10
|
-
|
|
11
|
-
.PHONY: help $(PLATFORMS)
|
|
12
|
-
|
|
13
|
-
help:
|
|
14
|
-
@echo "Usage:"
|
|
15
|
-
@echo " make <platform> # start all services concurrently"
|
|
16
|
-
@echo " make <platform> NAME=<service> # start one service"
|
|
17
|
-
@echo ""
|
|
18
|
-
@echo "Available platforms (dirs with scripts/run.sh):"
|
|
19
|
-
@if [ -z "$(PLATFORMS)" ]; then \
|
|
20
|
-
echo " (none — run: yjcli platform add)"; \
|
|
21
|
-
else \
|
|
22
|
-
for p in $(PLATFORMS); do echo " $$p"; done; \
|
|
23
|
-
fi
|
|
24
|
-
@echo ""
|
|
25
|
-
@echo "Example: make backend"
|
|
26
|
-
@echo " make backend NAME=api"
|
|
27
|
-
|
|
28
|
-
$(PLATFORMS):
|
|
29
|
-
@test -x "$@/scripts/run.sh" || (echo "missing: $@/scripts/run.sh"; exit 1)
|
|
30
|
-
@if [ -n "$(NAME)" ]; then \
|
|
31
|
-
"$@/scripts/run.sh" "$(NAME)" $(ARGS); \
|
|
32
|
-
else \
|
|
33
|
-
"$@/scripts/run.sh" $(ARGS); \
|
|
34
|
-
fi
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|