create-einja-app 0.3.2 → 0.3.3
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.
- package/README.md +33 -0
- package/dist/cli.js +60 -64
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/templates/default/.changeset/config.json +11 -0
- package/templates/default/.claude/hooks/einja/plan-mode-skill-loader.sh +5 -1
- package/templates/default/.claude/settings.json +14 -0
- package/templates/default/.claude/skills/cli-package-specs/SKILL.md +247 -0
- package/templates/default/.einja-sync.json +1 -1
- package/templates/default/.github/release.yml +10 -0
- package/templates/default/.github/workflows/changeset-status.yml +60 -0
- package/templates/default/.github/workflows/deploy-stable-branches.yml +289 -59
- package/templates/default/CLAUDE.md +35 -8
- package/templates/default/README.md +20 -8
- package/templates/default/docs/plans/agile-munching-knuth.md +161 -0
- package/templates/default/docs/plans/agile-riding-nova.md +158 -0
- package/templates/default/docs/plans/agile-wibbling-dusk.md +91 -0
- package/templates/default/docs/plans/ancient-watching-otter.md +152 -0
- package/templates/default/docs/plans/bright-sauteeing-bumblebee.md +30 -0
- package/templates/default/docs/plans/composed-doodling-mountain.md +362 -0
- package/templates/default/docs/plans/dazzling-foraging-cascade.md +32 -0
- package/templates/default/docs/plans/enchanted-wiggling-ember-agent-a5befd57d0ca4c7c7.md +177 -0
- package/templates/default/docs/plans/enchanted-wiggling-ember.md +170 -0
- package/templates/default/docs/plans/federated-questing-kahan.md +47 -0
- package/templates/default/docs/plans/flickering-pondering-hearth.md +26 -0
- package/templates/default/docs/plans/fluttering-snuggling-sprout.md +172 -0
- package/templates/default/docs/plans/generic-sleeping-snowglobe-agent-a41d8da.md +179 -0
- package/templates/default/docs/plans/generic-sleeping-snowglobe.md +108 -0
- package/templates/default/docs/plans/generic-snuggling-pudding.md +57 -0
- package/templates/default/docs/plans/idempotent-wiggling-cherny.md +122 -0
- package/templates/default/docs/plans/recursive-fluttering-mitten.md +176 -0
- package/templates/default/docs/plans/todo-create-einja-app-ux-fix.md +16 -0
- package/templates/default/docs/plans/todo-direnv-hang-fix.md +12 -0
- package/templates/default/docs/plans/todo-github-actions-release-workflow.md +34 -0
- package/templates/default/docs/plans/todo-issue-spec-rename.md +24 -0
- package/templates/default/docs/plans/todo-skill-creator-upgrade.md +18 -0
- package/templates/default/docs/plans/velvety-chasing-spark.md +28 -0
- package/templates/default/docs/plans/wondrous-strolling-crystal-agent-a0615fc.md +215 -0
- package/templates/default/docs/plans/wondrous-strolling-crystal.md +182 -0
- package/templates/default/docs/plans/zesty-roaming-steele.md +74 -0
- package/templates/default/gitignore +6 -2
- package/templates/default/package.json +6 -2
- package/templates/default/pnpm-lock.yaml +547 -0
- package/templates/default/scripts/ensure-serena.sh +2 -2
- package/templates/default/scripts/env-rotate-secrets.ts +66 -6
- package/templates/default/scripts/init-github.ts +363 -0
- package/templates/default/scripts/init.sh +11 -5
- package/templates/default/scripts/setup-dev.ts +16 -1
- package/templates/default/.claude/skills/create-einja-app-release/SKILL.md +0 -186
- package/templates/default/.claude/skills/dev-cli-release/SKILL.md +0 -173
- package/templates/default/.cursor/commands/spec-create.md +0 -227
- package/templates/default/.cursor/commands/task-exec.md +0 -287
- package/templates/default/.cursor/commands/update-docs-by-task-specs.md +0 -448
|
@@ -4,12 +4,20 @@ on:
|
|
|
4
4
|
push:
|
|
5
5
|
branches: [main, develop, staging]
|
|
6
6
|
|
|
7
|
+
# GITHUB_TOKENで作成されたpushイベントはデフォルトでワークフロー再トリガーしない
|
|
8
|
+
# 念のため明示的にbotコミットを除外(release-productionのバージョンバンプ対策)
|
|
9
|
+
|
|
10
|
+
permissions:
|
|
11
|
+
contents: write
|
|
12
|
+
|
|
7
13
|
concurrency:
|
|
8
14
|
group: deploy-${{ github.ref_name }}
|
|
9
15
|
cancel-in-progress: false
|
|
10
16
|
|
|
11
17
|
jobs:
|
|
12
18
|
ci:
|
|
19
|
+
# github-actions[bot] のバージョンバンプコミットはスキップ
|
|
20
|
+
if: "!contains(github.event.head_commit.message, 'chore: release v')"
|
|
13
21
|
runs-on: ubuntu-latest
|
|
14
22
|
services:
|
|
15
23
|
postgres:
|
|
@@ -89,35 +97,123 @@ jobs:
|
|
|
89
97
|
fi
|
|
90
98
|
echo "matrix=$MATRIX" >> $GITHUB_OUTPUT
|
|
91
99
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
100
|
+
# ========================================
|
|
101
|
+
# develop: 環境なし、承認なし、マイグレーションなし
|
|
102
|
+
# ========================================
|
|
103
|
+
deploy-develop:
|
|
104
|
+
needs: [ci, changes]
|
|
105
|
+
if: github.ref_name == 'develop' && needs.changes.outputs.deploy_matrix != '[]'
|
|
95
106
|
runs-on: ubuntu-latest
|
|
107
|
+
strategy:
|
|
108
|
+
fail-fast: false
|
|
109
|
+
matrix:
|
|
110
|
+
include: ${{ fromJSON(needs.changes.outputs.deploy_matrix) }}
|
|
111
|
+
env:
|
|
112
|
+
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
|
|
113
|
+
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
|
|
114
|
+
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
|
115
|
+
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
|
96
116
|
steps:
|
|
97
117
|
- uses: actions/checkout@v4
|
|
98
118
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
119
|
+
- name: Setup Environment
|
|
120
|
+
uses: ./.github/actions/setup
|
|
121
|
+
|
|
122
|
+
- name: Resolve Vercel Project ID
|
|
123
|
+
id: resolve
|
|
124
|
+
run: |
|
|
125
|
+
case "${{ matrix.app }}" in
|
|
126
|
+
web) echo "project_id=${{ secrets.VERCEL_PROJECT_ID_WEB }}" >> $GITHUB_OUTPUT ;;
|
|
127
|
+
admin) echo "project_id=${{ secrets.VERCEL_PROJECT_ID_ADMIN }}" >> $GITHUB_OUTPUT ;;
|
|
128
|
+
esac
|
|
129
|
+
|
|
130
|
+
- name: Set VERCEL_PROJECT_ID
|
|
131
|
+
run: echo "VERCEL_PROJECT_ID=${{ steps.resolve.outputs.project_id }}" >> $GITHUB_ENV
|
|
132
|
+
|
|
133
|
+
- name: Install Vercel CLI
|
|
134
|
+
run: pnpm add -g vercel@latest
|
|
135
|
+
|
|
136
|
+
- name: Set deploy environment
|
|
137
|
+
run: |
|
|
138
|
+
echo "DEPLOY_DOTENV_FILE=$GITHUB_WORKSPACE/.env.develop" >> $GITHUB_ENV
|
|
139
|
+
echo "DEPLOY_VERCEL_ENV=preview" >> $GITHUB_ENV
|
|
140
|
+
echo "DEPLOY_PROD_FLAG=" >> $GITHUB_ENV
|
|
141
|
+
echo "DEPLOY_RUN_ALIAS=true" >> $GITHUB_ENV
|
|
142
|
+
|
|
143
|
+
- name: Extract alias domain
|
|
144
|
+
run: |
|
|
145
|
+
case "${{ matrix.app }}" in
|
|
146
|
+
web)
|
|
147
|
+
npx dotenvx run -f ${{ env.DEPLOY_DOTENV_FILE }} -- bash -c '
|
|
148
|
+
echo "VERCEL_ALIAS_DOMAIN=$VERCEL_ALIAS_DOMAIN_WEB" >> "$GITHUB_ENV"
|
|
149
|
+
'
|
|
150
|
+
;;
|
|
151
|
+
admin)
|
|
152
|
+
npx dotenvx run -f ${{ env.DEPLOY_DOTENV_FILE }} -- bash -c '
|
|
153
|
+
echo "VERCEL_ALIAS_DOMAIN=$VERCEL_ALIAS_DOMAIN_ADMIN" >> "$GITHUB_ENV"
|
|
154
|
+
'
|
|
155
|
+
;;
|
|
156
|
+
esac
|
|
157
|
+
env:
|
|
158
|
+
DOTENV_PRIVATE_KEY_DEVELOP: ${{ secrets.DOTENV_PRIVATE_KEY_DEVELOP }}
|
|
159
|
+
|
|
160
|
+
- name: Pull Vercel Environment
|
|
161
|
+
run: vercel pull --yes --environment=${{ env.DEPLOY_VERCEL_ENV }} --token=$VERCEL_TOKEN
|
|
162
|
+
|
|
163
|
+
- name: Build Project
|
|
164
|
+
run: |
|
|
165
|
+
npx dotenvx run -f ${{ env.DEPLOY_DOTENV_FILE }} -- \
|
|
166
|
+
vercel build ${{ env.DEPLOY_PROD_FLAG }} --token=$VERCEL_TOKEN
|
|
167
|
+
env:
|
|
168
|
+
DOTENV_PRIVATE_KEY_DEVELOP: ${{ secrets.DOTENV_PRIVATE_KEY_DEVELOP }}
|
|
169
|
+
|
|
170
|
+
- name: Deploy to Vercel
|
|
171
|
+
id: deploy
|
|
172
|
+
run: |
|
|
173
|
+
npx dotenvx run -f $DEPLOY_DOTENV_FILE -- bash -c '
|
|
174
|
+
declare -a ENV_FLAGS=()
|
|
175
|
+
while IFS= read -r key; do
|
|
176
|
+
case "$key" in
|
|
177
|
+
NEON_*|VERCEL_ALIAS_DOMAIN_*|DOTENV_PUBLIC_KEY_*) continue ;;
|
|
178
|
+
esac
|
|
179
|
+
value="${!key}"
|
|
180
|
+
if [ -n "$value" ]; then
|
|
181
|
+
echo "::add-mask::${value}"
|
|
182
|
+
fi
|
|
183
|
+
ENV_FLAGS+=("--env" "${key}=${value}")
|
|
184
|
+
done < <(grep -E "^[A-Z_][A-Z0-9_]*=\"?encrypted:" "$DEPLOY_DOTENV_FILE" | cut -d= -f1)
|
|
185
|
+
|
|
186
|
+
echo "Deploying with ${#ENV_FLAGS[@]} runtime env vars..."
|
|
187
|
+
DEPLOY_URL=$(vercel deploy --prebuilt $DEPLOY_PROD_FLAG "${ENV_FLAGS[@]}" --token="$VERCEL_TOKEN")
|
|
188
|
+
echo "url=$DEPLOY_URL" >> "$GITHUB_OUTPUT"
|
|
189
|
+
'
|
|
190
|
+
env:
|
|
191
|
+
DOTENV_PRIVATE_KEY_DEVELOP: ${{ secrets.DOTENV_PRIVATE_KEY_DEVELOP }}
|
|
192
|
+
|
|
193
|
+
- name: Set Vercel alias
|
|
194
|
+
run: vercel alias ${{ steps.deploy.outputs.url }} "${{ env.VERCEL_ALIAS_DOMAIN }}" --token=$VERCEL_TOKEN
|
|
195
|
+
|
|
196
|
+
# ========================================
|
|
197
|
+
# staging: staging環境、承認なし
|
|
198
|
+
# ========================================
|
|
199
|
+
migrate-staging:
|
|
200
|
+
needs: ci
|
|
201
|
+
if: github.ref_name == 'staging'
|
|
202
|
+
runs-on: ubuntu-latest
|
|
203
|
+
steps:
|
|
204
|
+
- uses: actions/checkout@v4
|
|
107
205
|
|
|
108
|
-
# staging: ステージング環境マイグレーション(シード無効)
|
|
109
206
|
- name: Migrate staging
|
|
110
|
-
if: github.ref_name == 'staging'
|
|
111
207
|
uses: ./.github/actions/migrate
|
|
112
208
|
with:
|
|
113
209
|
dotenv-file: ${{ github.workspace }}/.env.staging
|
|
114
210
|
dotenv-private-key: ${{ secrets.DOTENV_PRIVATE_KEY_STAGING }}
|
|
115
211
|
run-seed: 'false'
|
|
116
212
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
213
|
+
deploy-staging:
|
|
214
|
+
needs: [ci, migrate-staging, changes]
|
|
215
|
+
if: github.ref_name == 'staging' && needs.changes.outputs.deploy_matrix != '[]'
|
|
216
|
+
environment: staging
|
|
121
217
|
runs-on: ubuntu-latest
|
|
122
218
|
strategy:
|
|
123
219
|
fail-fast: false
|
|
@@ -148,35 +244,14 @@ jobs:
|
|
|
148
244
|
- name: Install Vercel CLI
|
|
149
245
|
run: pnpm add -g vercel@latest
|
|
150
246
|
|
|
151
|
-
|
|
152
|
-
- name: Determine environment
|
|
247
|
+
- name: Set deploy environment
|
|
153
248
|
run: |
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
echo "DEPLOY_VERCEL_ENV=production" >> $GITHUB_ENV
|
|
159
|
-
echo "DEPLOY_PROD_FLAG=--prod" >> $GITHUB_ENV
|
|
160
|
-
echo "DEPLOY_RUN_ALIAS=false" >> $GITHUB_ENV
|
|
161
|
-
;;
|
|
162
|
-
develop)
|
|
163
|
-
echo "DEPLOY_DOTENV_FILE=$GITHUB_WORKSPACE/.env.develop" >> $GITHUB_ENV
|
|
164
|
-
echo "DEPLOY_VERCEL_ENV=preview" >> $GITHUB_ENV
|
|
165
|
-
echo "DEPLOY_PROD_FLAG=" >> $GITHUB_ENV
|
|
166
|
-
echo "DEPLOY_RUN_ALIAS=true" >> $GITHUB_ENV
|
|
167
|
-
;;
|
|
168
|
-
staging)
|
|
169
|
-
echo "DEPLOY_DOTENV_FILE=$GITHUB_WORKSPACE/.env.staging" >> $GITHUB_ENV
|
|
170
|
-
echo "DEPLOY_VERCEL_ENV=preview" >> $GITHUB_ENV
|
|
171
|
-
echo "DEPLOY_PROD_FLAG=" >> $GITHUB_ENV
|
|
172
|
-
echo "DEPLOY_RUN_ALIAS=true" >> $GITHUB_ENV
|
|
173
|
-
;;
|
|
174
|
-
esac
|
|
175
|
-
echo "Branch: $BRANCH, Environment: $(cat $GITHUB_ENV | grep DEPLOY_VERCEL_ENV)"
|
|
249
|
+
echo "DEPLOY_DOTENV_FILE=$GITHUB_WORKSPACE/.env.staging" >> $GITHUB_ENV
|
|
250
|
+
echo "DEPLOY_VERCEL_ENV=preview" >> $GITHUB_ENV
|
|
251
|
+
echo "DEPLOY_PROD_FLAG=" >> $GITHUB_ENV
|
|
252
|
+
echo "DEPLOY_RUN_ALIAS=true" >> $GITHUB_ENV
|
|
176
253
|
|
|
177
|
-
# Extract alias domain(自アプリ分のみ)
|
|
178
254
|
- name: Extract alias domain
|
|
179
|
-
if: env.DEPLOY_RUN_ALIAS == 'true'
|
|
180
255
|
run: |
|
|
181
256
|
case "${{ matrix.app }}" in
|
|
182
257
|
web)
|
|
@@ -192,15 +267,141 @@ jobs:
|
|
|
192
267
|
esac
|
|
193
268
|
env:
|
|
194
269
|
DOTENV_PRIVATE_KEY_STAGING: ${{ secrets.DOTENV_PRIVATE_KEY_STAGING }}
|
|
195
|
-
DOTENV_PRIVATE_KEY_DEVELOP: ${{ secrets.DOTENV_PRIVATE_KEY_DEVELOP }}
|
|
196
270
|
|
|
197
|
-
# Vercel pull
|
|
198
271
|
- name: Pull Vercel Environment
|
|
199
272
|
run: vercel pull --yes --environment=${{ env.DEPLOY_VERCEL_ENV }} --token=$VERCEL_TOKEN
|
|
200
273
|
|
|
201
|
-
|
|
274
|
+
- name: Build Project
|
|
275
|
+
run: |
|
|
276
|
+
npx dotenvx run -f ${{ env.DEPLOY_DOTENV_FILE }} -- \
|
|
277
|
+
vercel build ${{ env.DEPLOY_PROD_FLAG }} --token=$VERCEL_TOKEN
|
|
278
|
+
env:
|
|
279
|
+
DOTENV_PRIVATE_KEY_STAGING: ${{ secrets.DOTENV_PRIVATE_KEY_STAGING }}
|
|
280
|
+
|
|
281
|
+
- name: Deploy to Vercel
|
|
282
|
+
id: deploy
|
|
283
|
+
run: |
|
|
284
|
+
npx dotenvx run -f $DEPLOY_DOTENV_FILE -- bash -c '
|
|
285
|
+
declare -a ENV_FLAGS=()
|
|
286
|
+
while IFS= read -r key; do
|
|
287
|
+
case "$key" in
|
|
288
|
+
NEON_*|VERCEL_ALIAS_DOMAIN_*|DOTENV_PUBLIC_KEY_*) continue ;;
|
|
289
|
+
esac
|
|
290
|
+
value="${!key}"
|
|
291
|
+
if [ -n "$value" ]; then
|
|
292
|
+
echo "::add-mask::${value}"
|
|
293
|
+
fi
|
|
294
|
+
ENV_FLAGS+=("--env" "${key}=${value}")
|
|
295
|
+
done < <(grep -E "^[A-Z_][A-Z0-9_]*=\"?encrypted:" "$DEPLOY_DOTENV_FILE" | cut -d= -f1)
|
|
296
|
+
|
|
297
|
+
echo "Deploying with ${#ENV_FLAGS[@]} runtime env vars..."
|
|
298
|
+
DEPLOY_URL=$(vercel deploy --prebuilt $DEPLOY_PROD_FLAG "${ENV_FLAGS[@]}" --token="$VERCEL_TOKEN")
|
|
299
|
+
echo "url=$DEPLOY_URL" >> "$GITHUB_OUTPUT"
|
|
300
|
+
'
|
|
301
|
+
env:
|
|
302
|
+
DOTENV_PRIVATE_KEY_STAGING: ${{ secrets.DOTENV_PRIVATE_KEY_STAGING }}
|
|
303
|
+
|
|
304
|
+
- name: Set Vercel alias
|
|
305
|
+
run: vercel alias ${{ steps.deploy.outputs.url }} "${{ env.VERCEL_ALIAS_DOMAIN }}" --token=$VERCEL_TOKEN
|
|
306
|
+
|
|
307
|
+
# staging: PreRelease作成(changeset未消費)
|
|
308
|
+
release-staging:
|
|
309
|
+
needs: deploy-staging
|
|
310
|
+
if: github.ref_name == 'staging'
|
|
311
|
+
runs-on: ubuntu-latest
|
|
312
|
+
steps:
|
|
313
|
+
- uses: actions/checkout@v4
|
|
314
|
+
with:
|
|
315
|
+
fetch-depth: 0
|
|
316
|
+
|
|
317
|
+
- name: Check for changesets
|
|
318
|
+
id: check
|
|
319
|
+
run: |
|
|
320
|
+
COUNT=$(ls .changeset/*.md 2>/dev/null | grep -cv README.md || echo 0)
|
|
321
|
+
echo "has_changesets=$([[ $COUNT -gt 0 ]] && echo true || echo false)" >> $GITHUB_OUTPUT
|
|
322
|
+
|
|
323
|
+
- name: Create PreRelease tag
|
|
324
|
+
if: steps.check.outputs.has_changesets == 'true'
|
|
325
|
+
id: tag
|
|
326
|
+
run: |
|
|
327
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
328
|
+
TAG="v${VERSION}-rc.${{ github.run_number }}"
|
|
329
|
+
git tag "$TAG"
|
|
330
|
+
git push origin "$TAG"
|
|
331
|
+
echo "tag=$TAG" >> $GITHUB_OUTPUT
|
|
332
|
+
|
|
333
|
+
- name: Create GitHub PreRelease
|
|
334
|
+
if: steps.tag.outputs.tag
|
|
335
|
+
run: |
|
|
336
|
+
PREV=$(git tag --list 'v*-rc.*' --sort=-v:refname | grep -v "${{ steps.tag.outputs.tag }}" | head -1)
|
|
337
|
+
OPTS="--prerelease --target staging --generate-notes"
|
|
338
|
+
[[ -n "$PREV" ]] && OPTS="$OPTS --notes-start-tag $PREV"
|
|
339
|
+
gh release create "${{ steps.tag.outputs.tag }}" --title "Pre-release ${{ steps.tag.outputs.tag }}" $OPTS
|
|
340
|
+
env:
|
|
341
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
342
|
+
|
|
343
|
+
# ========================================
|
|
344
|
+
# main: production環境、1名承認 → migrate → deploy → release
|
|
345
|
+
# ========================================
|
|
346
|
+
migrate-production:
|
|
347
|
+
needs: ci
|
|
348
|
+
if: github.ref_name == 'main'
|
|
349
|
+
environment: production
|
|
350
|
+
runs-on: ubuntu-latest
|
|
351
|
+
steps:
|
|
352
|
+
- uses: actions/checkout@v4
|
|
353
|
+
|
|
354
|
+
- name: Migrate production
|
|
355
|
+
uses: ./.github/actions/migrate
|
|
356
|
+
with:
|
|
357
|
+
dotenv-file: ${{ github.workspace }}/.env.production
|
|
358
|
+
dotenv-private-key: ${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}
|
|
359
|
+
run-seed: 'false'
|
|
360
|
+
|
|
361
|
+
deploy-production:
|
|
362
|
+
needs: [migrate-production, changes]
|
|
363
|
+
if: github.ref_name == 'main' && needs.changes.outputs.deploy_matrix != '[]'
|
|
364
|
+
runs-on: ubuntu-latest
|
|
365
|
+
strategy:
|
|
366
|
+
fail-fast: false
|
|
367
|
+
matrix:
|
|
368
|
+
include: ${{ fromJSON(needs.changes.outputs.deploy_matrix) }}
|
|
369
|
+
env:
|
|
370
|
+
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
|
|
371
|
+
VERCEL_ORG_ID: ${{ secrets.VERCEL_ORG_ID }}
|
|
372
|
+
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
|
|
373
|
+
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}
|
|
374
|
+
steps:
|
|
375
|
+
- uses: actions/checkout@v4
|
|
376
|
+
|
|
377
|
+
- name: Setup Environment
|
|
378
|
+
uses: ./.github/actions/setup
|
|
379
|
+
|
|
380
|
+
- name: Resolve Vercel Project ID
|
|
381
|
+
id: resolve
|
|
382
|
+
run: |
|
|
383
|
+
case "${{ matrix.app }}" in
|
|
384
|
+
web) echo "project_id=${{ secrets.VERCEL_PROJECT_ID_WEB }}" >> $GITHUB_OUTPUT ;;
|
|
385
|
+
admin) echo "project_id=${{ secrets.VERCEL_PROJECT_ID_ADMIN }}" >> $GITHUB_OUTPUT ;;
|
|
386
|
+
esac
|
|
387
|
+
|
|
388
|
+
- name: Set VERCEL_PROJECT_ID
|
|
389
|
+
run: echo "VERCEL_PROJECT_ID=${{ steps.resolve.outputs.project_id }}" >> $GITHUB_ENV
|
|
390
|
+
|
|
391
|
+
- name: Install Vercel CLI
|
|
392
|
+
run: pnpm add -g vercel@latest
|
|
393
|
+
|
|
394
|
+
- name: Set deploy environment
|
|
395
|
+
run: |
|
|
396
|
+
echo "DEPLOY_DOTENV_FILE=$GITHUB_WORKSPACE/.env.production" >> $GITHUB_ENV
|
|
397
|
+
echo "DEPLOY_VERCEL_ENV=production" >> $GITHUB_ENV
|
|
398
|
+
echo "DEPLOY_PROD_FLAG=--prod" >> $GITHUB_ENV
|
|
399
|
+
echo "DEPLOY_RUN_ALIAS=false" >> $GITHUB_ENV
|
|
400
|
+
|
|
401
|
+
- name: Pull Vercel Environment
|
|
402
|
+
run: vercel pull --yes --environment=${{ env.DEPLOY_VERCEL_ENV }} --token=$VERCEL_TOKEN
|
|
403
|
+
|
|
202
404
|
- name: Sync environment variables to Vercel
|
|
203
|
-
if: github.ref_name == 'main'
|
|
204
405
|
run: |
|
|
205
406
|
npx dotenvx run -f ${{ env.DEPLOY_DOTENV_FILE }} -- bash -c '
|
|
206
407
|
grep -E "^[A-Z_][A-Z0-9_]*=\"?encrypted:" ${{ env.DEPLOY_DOTENV_FILE }} | cut -d= -f1 | while read -r key; do
|
|
@@ -218,22 +419,16 @@ jobs:
|
|
|
218
419
|
env:
|
|
219
420
|
DOTENV_PRIVATE_KEY_PRODUCTION: ${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}
|
|
220
421
|
|
|
221
|
-
# Re-pull after sync
|
|
222
422
|
- name: Re-pull Vercel Environment after sync
|
|
223
|
-
if: github.ref_name == 'main'
|
|
224
423
|
run: vercel pull --yes --environment=${{ env.DEPLOY_VERCEL_ENV }} --token=$VERCEL_TOKEN
|
|
225
424
|
|
|
226
|
-
# Vercel build (dotenvxでアプリ環境変数を注入)
|
|
227
425
|
- name: Build Project
|
|
228
426
|
run: |
|
|
229
427
|
npx dotenvx run -f ${{ env.DEPLOY_DOTENV_FILE }} -- \
|
|
230
428
|
vercel build ${{ env.DEPLOY_PROD_FLAG }} --token=$VERCEL_TOKEN
|
|
231
429
|
env:
|
|
232
430
|
DOTENV_PRIVATE_KEY_PRODUCTION: ${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}
|
|
233
|
-
DOTENV_PRIVATE_KEY_STAGING: ${{ secrets.DOTENV_PRIVATE_KEY_STAGING }}
|
|
234
|
-
DOTENV_PRIVATE_KEY_DEVELOP: ${{ secrets.DOTENV_PRIVATE_KEY_DEVELOP }}
|
|
235
431
|
|
|
236
|
-
# Vercel deploy
|
|
237
432
|
- name: Deploy to Vercel
|
|
238
433
|
id: deploy
|
|
239
434
|
run: |
|
|
@@ -256,10 +451,45 @@ jobs:
|
|
|
256
451
|
'
|
|
257
452
|
env:
|
|
258
453
|
DOTENV_PRIVATE_KEY_PRODUCTION: ${{ secrets.DOTENV_PRIVATE_KEY_PRODUCTION }}
|
|
259
|
-
DOTENV_PRIVATE_KEY_STAGING: ${{ secrets.DOTENV_PRIVATE_KEY_STAGING }}
|
|
260
|
-
DOTENV_PRIVATE_KEY_DEVELOP: ${{ secrets.DOTENV_PRIVATE_KEY_DEVELOP }}
|
|
261
454
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
455
|
+
# main: changeset消費 + Release作成
|
|
456
|
+
release-production:
|
|
457
|
+
needs: deploy-production
|
|
458
|
+
if: always() && github.ref_name == 'main' && needs.deploy-production.result != 'failure'
|
|
459
|
+
runs-on: ubuntu-latest
|
|
460
|
+
steps:
|
|
461
|
+
- uses: actions/checkout@v4
|
|
462
|
+
with:
|
|
463
|
+
fetch-depth: 0
|
|
464
|
+
|
|
465
|
+
- name: Setup
|
|
466
|
+
uses: ./.github/actions/setup
|
|
467
|
+
|
|
468
|
+
- name: Check for changesets
|
|
469
|
+
id: check
|
|
470
|
+
run: |
|
|
471
|
+
COUNT=$(ls .changeset/*.md 2>/dev/null | grep -cv README.md || echo 0)
|
|
472
|
+
echo "has_changesets=$([[ $COUNT -gt 0 ]] && echo true || echo false)" >> $GITHUB_OUTPUT
|
|
473
|
+
|
|
474
|
+
- name: Version packages
|
|
475
|
+
if: steps.check.outputs.has_changesets == 'true'
|
|
476
|
+
run: npx changeset version
|
|
477
|
+
|
|
478
|
+
- name: Commit version bump and create Release
|
|
479
|
+
if: steps.check.outputs.has_changesets == 'true'
|
|
480
|
+
id: release
|
|
481
|
+
run: |
|
|
482
|
+
VERSION=$(node -p "require('./package.json').version")
|
|
483
|
+
TAG="v${VERSION}"
|
|
484
|
+
git config user.name "github-actions[bot]"
|
|
485
|
+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
486
|
+
git add -A
|
|
487
|
+
git commit -m "chore: release ${TAG}" || echo "No changes"
|
|
488
|
+
git tag "$TAG"
|
|
489
|
+
git push origin main --follow-tags
|
|
490
|
+
PREV=$(git tag --list 'v*' --sort=-v:refname | grep -v 'rc' | grep -v "$TAG" | head -1)
|
|
491
|
+
OPTS="--target main --generate-notes"
|
|
492
|
+
[[ -n "$PREV" ]] && OPTS="$OPTS --notes-start-tag $PREV"
|
|
493
|
+
gh release create "$TAG" --title "Release ${TAG}" $OPTS
|
|
494
|
+
env:
|
|
495
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
3. **影響範囲の最小化**: 変更は必要な箇所のみ。関係ないコードに触れない
|
|
11
11
|
4. **直接実装の禁止**: あなたは絶対に直接実装を行わない。すべての作業はsubagentに委託し、可能な限り並行で呼び出す。サブエージェントの出力はユーザにも見える場所に出力すること
|
|
12
12
|
5. **実装品質の自己検証**: 複雑な変更では完了前に「よりエレガントな方法はないか」を自問する。ただし単純な修正には不要
|
|
13
|
+
6. **Skill-First原則**: 実装着手前に `einja-skill-first` Skillで「Skillを先に作るべきか」を評価する。反復性のある作業はSkill化してから本作業を開始する
|
|
13
14
|
|
|
14
15
|
## Agent Teams の使用制限
|
|
15
16
|
|
|
@@ -26,7 +27,6 @@
|
|
|
26
27
|
|
|
27
28
|
| 作業 | 委託先 |
|
|
28
29
|
|------|--------|
|
|
29
|
-
| コンフリクト解消 | `conflict-resolver` |
|
|
30
30
|
| Codex作業(レビュー・実装支援等) | `codex-agent` |
|
|
31
31
|
| フロントエンド アーキテクチャ設計 | `frontend-architect` |
|
|
32
32
|
| フロントエンド デザイン実装 | `design-engineer` |
|
|
@@ -40,11 +40,21 @@
|
|
|
40
40
|
| `einja-task-commit` | コミット・プッシュ |
|
|
41
41
|
| `einja-conflict-resolver` | gitコンフリクト解消 |
|
|
42
42
|
| `einja-skill-creator` | Skill作成・更新 |
|
|
43
|
-
| `einja-skill-first` | 作業前のSkill作成必要性評価(Plan/spec-create時に自動起動) |
|
|
43
|
+
| `einja-skill-first` | 作業前のSkill作成必要性評価(Plan/einja-issue-spec-create時に自動起動) |
|
|
44
44
|
| `einja-infra-maintenance` | インフラ環境セットアップ・メンテナンス |
|
|
45
|
-
| `einja:issue-exec` | Issue全体の階層的並列実行(
|
|
46
|
-
| `einja
|
|
47
|
-
| `einja
|
|
45
|
+
| `einja:issue-exec` | Issue全体の階層的並列実行(Command) |
|
|
46
|
+
| `einja-task-exec` | タスクグループ実行(Skill tool) |
|
|
47
|
+
| `einja-issue-spec-create` | Issue仕様書作成(Skill tool) |
|
|
48
|
+
|
|
49
|
+
#### サブエージェント質問プロトコル(PENDING_QUESTIONS)
|
|
50
|
+
|
|
51
|
+
サブエージェントではAskUserQuestionが動作しないため、質問が必要な場合は `## PENDING_QUESTIONS` 形式で返却される。
|
|
52
|
+
|
|
53
|
+
サブエージェント出力に `## PENDING_QUESTIONS` が含まれている場合:
|
|
54
|
+
1. 質問内容を解析し、AskUserQuestionでユーザーに確認する
|
|
55
|
+
2. Agent toolの `resume` パラメータで同じサブエージェントを再開(コンテキスト維持)
|
|
56
|
+
3. プロンプトにユーザーの回答を含めて渡す(例: `ユーザーの回答: Q1→A、Q2→B。これを踏まえて作業を継続してください。`)
|
|
57
|
+
4. 再度PENDING_QUESTIONSがある場合は同様に処理(最大2回まで)
|
|
48
58
|
|
|
49
59
|
## コード変更時の動作方針
|
|
50
60
|
|
|
@@ -165,6 +175,11 @@ Turborepoモノレポ構成(pnpm workspaces)。詳細が必要な場合は
|
|
|
165
175
|
- 番号付きリスト: 詳細説明が必要な場合
|
|
166
176
|
- 推奨オプションには `(推奨)` と理由を付記
|
|
167
177
|
|
|
178
|
+
### 選択肢の記述ルール
|
|
179
|
+
- 各選択肢の `description` に**必ず詳細説明・注意点・補足**を記載する
|
|
180
|
+
- トレードオフ、影響範囲、前提条件など判断に必要な情報を含める
|
|
181
|
+
- ラベルだけで選択させない。ユーザーが十分な情報に基づいて判断できるようにする
|
|
182
|
+
|
|
168
183
|
## 報告ルール
|
|
169
184
|
|
|
170
185
|
### 出力形式
|
|
@@ -222,9 +237,8 @@ Turborepoモノレポ構成(pnpm workspaces)。詳細が必要な場合は
|
|
|
222
237
|
|
|
223
238
|
| キーワード | 使用するSkill |
|
|
224
239
|
|-----------|--------------|
|
|
225
|
-
| `einja cli` `@einja/dev-cli` `公開` `リリース` `publish` `release` | `.claude/skills/
|
|
226
|
-
| `
|
|
227
|
-
| `インフラ` `環境変数管理` `Vercel` `Neon` `デプロイ設定` `GitHub Secrets` `環境セットアップ` `GitHub Actions` `CI/CD` `ワークフロー` | `.claude/skills/einja-infra-maintenance/SKILL.md` |
|
|
240
|
+
| `einja cli` `@einja/dev-cli` `create-einja-app` `公開` `リリース` `publish` `release` | `.claude/skills/einja-npm-release/SKILL.md` |
|
|
241
|
+
| `インフラ` `環境変数管理` `Vercel` `Neon` `デプロイ設定` `GitHub Secrets` `環境セットアップ` `ローカルセットアップ` `ローカル環境` `セットアップ` `GitHub Actions` `CI/CD` `ワークフロー` | `.claude/skills/einja-infra-maintenance/SKILL.md` |
|
|
228
242
|
| `Skill作るべき?` `Skill化` `skill-first` `Skill-first` | `.claude/skills/einja-skill-first/SKILL.md` |
|
|
229
243
|
|
|
230
244
|
### CLIパッケージの二重管理禁止
|
|
@@ -244,4 +258,17 @@ Turborepoモノレポ構成(pnpm workspaces)。詳細が必要な場合は
|
|
|
244
258
|
| `scripts/` (`_`プレフィクス除く) | `presets/default/scripts/` | 単純コピー |
|
|
245
259
|
|
|
246
260
|
**コピー先のファイルは直接編集禁止**(ビルド時に上書きされる)
|
|
261
|
+
|
|
262
|
+
### パッケージビルド仕様(テンプレートリポジトリ限定)
|
|
263
|
+
|
|
264
|
+
`@einja/dev-cli` と `create-einja-app` の2パッケージのビルド・テンプレート仕様については、以下のSkillを参照すること:
|
|
265
|
+
|
|
266
|
+
`.claude/skills/cli-package-specs/SKILL.md`
|
|
267
|
+
|
|
268
|
+
### マネージドディレクトリの編集について(テンプレートリポジトリ限定)
|
|
269
|
+
|
|
270
|
+
このリポジトリは `docs/einja/` の**原本(Single Source of Truth)**である。
|
|
271
|
+
上記「マネージドディレクトリ(編集禁止)」ルールは下流リポジトリ(create-einja-appで生成されたプロジェクト)向けであり、
|
|
272
|
+
**このリポジトリでは `docs/einja/` 配下の全ファイルを編集してよい**。
|
|
273
|
+
変更はビルド時に `presets/default/` へ自動コピーされる。
|
|
247
274
|
<!-- @einja:excluded:end -->
|
|
@@ -14,13 +14,19 @@ Turborepo + Next.js 15 + Auth.js + Prisma 構成のプロジェクトテンプ
|
|
|
14
14
|
```
|
|
15
15
|
einja-management-template/
|
|
16
16
|
├── apps/
|
|
17
|
-
│
|
|
17
|
+
│ ├── web/ # メイン管理画面アプリ
|
|
18
|
+
│ │ ├── src/
|
|
19
|
+
│ │ │ ├── app/ # Next.js App Router
|
|
20
|
+
│ │ │ ├── components/ # アプリ固有のコンポーネント
|
|
21
|
+
│ │ │ └── lib/
|
|
22
|
+
│ │ │ ├── auth/ # アプリ固有の認証設定
|
|
23
|
+
│ │ │ └── ... # アプリ固有のユーティリティ
|
|
24
|
+
│ │ ├── package.json
|
|
25
|
+
│ │ └── tsconfig.json
|
|
26
|
+
│ └── admin/ # 管理者画面アプリ
|
|
18
27
|
│ ├── src/
|
|
19
28
|
│ │ ├── app/ # Next.js App Router
|
|
20
|
-
│ │
|
|
21
|
-
│ │ └── lib/
|
|
22
|
-
│ │ ├── auth/ # アプリ固有の認証設定
|
|
23
|
-
│ │ └── ... # アプリ固有のユーティリティ
|
|
29
|
+
│ │ └── components/ # アプリ固有のコンポーネント
|
|
24
30
|
│ ├── package.json
|
|
25
31
|
│ └── tsconfig.json
|
|
26
32
|
├── packages/
|
|
@@ -38,7 +44,9 @@ einja-management-template/
|
|
|
38
44
|
│ │ └── src/
|
|
39
45
|
│ │ ├── domain/ # ドメイン層
|
|
40
46
|
│ │ ├── infrastructure/ # Prismaクライアント等
|
|
41
|
-
│ │
|
|
47
|
+
│ │ ├── core/ # 共通コアモジュール
|
|
48
|
+
│ │ └── testing/ # テストユーティリティ
|
|
49
|
+
│ ├── admin-ui/ # 管理者画面専用UIコンポーネント
|
|
42
50
|
│ └── ui/ # 共通UIコンポーネント(shadcn/ui)
|
|
43
51
|
├── turbo.json # Turborepoの設定
|
|
44
52
|
├── pnpm-workspace.yaml # pnpmワークスペース設定
|
|
@@ -61,6 +69,8 @@ einja-management-template/
|
|
|
61
69
|
|
|
62
70
|
### 開発環境セットアップ
|
|
63
71
|
|
|
72
|
+
> 📖 各コマンドで何が実行されるかの詳細は [セットアップフローガイド](docs/einja/instructions/setup-flow.md) を参照してください。
|
|
73
|
+
|
|
64
74
|
#### 初回セットアップ(初めての方)
|
|
65
75
|
|
|
66
76
|
```bash
|
|
@@ -171,13 +181,14 @@ pnpm db:studio # Prisma Studio起動
|
|
|
171
181
|
# 特定のワークスペースでコマンド実行
|
|
172
182
|
pnpm --filter @repo/web dev
|
|
173
183
|
pnpm --filter @repo/web build
|
|
184
|
+
pnpm --filter @repo/admin dev
|
|
174
185
|
```
|
|
175
186
|
|
|
176
187
|
### データベース設定
|
|
177
188
|
|
|
178
189
|
#### Docker Compose サービス
|
|
179
190
|
|
|
180
|
-
- **postgres**: PostgreSQL
|
|
191
|
+
- **postgres**: PostgreSQL 16
|
|
181
192
|
- ポート: `${POSTGRES_PORT:-25432}` (ホスト) → 5432 (コンテナ)
|
|
182
193
|
- データベース: ブランチ名から自動生成(例: `main`, `feature_auth`)
|
|
183
194
|
- ユーザー: `postgres`
|
|
@@ -190,7 +201,7 @@ pnpm --filter @repo/web build
|
|
|
190
201
|
docker-compose logs -f postgres
|
|
191
202
|
|
|
192
203
|
# データベースに直接接続
|
|
193
|
-
docker-compose exec postgres psql -U postgres -d
|
|
204
|
+
docker-compose exec postgres psql -U postgres -d main
|
|
194
205
|
|
|
195
206
|
# データベースをリセット
|
|
196
207
|
docker-compose down -v
|
|
@@ -220,6 +231,7 @@ pnpm db:studio
|
|
|
220
231
|
- **@repo/config**: Biome, TypeScriptの共通設定
|
|
221
232
|
- **@repo/front-core**: フロントエンド共通層(認証共通設定、hooks、utils、context)
|
|
222
233
|
- **@repo/server-core**: バックエンド共通層(Prismaクライアント・スキーマ、ドメインロジック)
|
|
234
|
+
- **@repo/admin-ui**: 管理者画面専用UIコンポーネント
|
|
223
235
|
- **@repo/ui**: 共通UIコンポーネント(shadcn/ui)
|
|
224
236
|
|
|
225
237
|
### 開発ワークフロー
|