@kennethsolomon/shipkit 1.0.0
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 +321 -0
- package/bin/shipkit.js +146 -0
- package/commands/sk/brainstorm.md +63 -0
- package/commands/sk/branch.md +35 -0
- package/commands/sk/config.md +96 -0
- package/commands/sk/execute-plan.md +85 -0
- package/commands/sk/features.md +238 -0
- package/commands/sk/finish-feature.md +154 -0
- package/commands/sk/help.md +103 -0
- package/commands/sk/hotfix.md +61 -0
- package/commands/sk/plan.md +30 -0
- package/commands/sk/release.md +72 -0
- package/commands/sk/security-check.md +188 -0
- package/commands/sk/set-profile.md +71 -0
- package/commands/sk/status.md +25 -0
- package/commands/sk/update-task.md +35 -0
- package/commands/sk/write-plan.md +72 -0
- package/package.json +23 -0
- package/skills/sk:accessibility/LICENSE.txt +177 -0
- package/skills/sk:accessibility/SKILL.md +150 -0
- package/skills/sk:api-design/LICENSE.txt +177 -0
- package/skills/sk:api-design/SKILL.md +158 -0
- package/skills/sk:brainstorming/SKILL.md +124 -0
- package/skills/sk:debug/SKILL.md +252 -0
- package/skills/sk:debug/debug_conductor.py +177 -0
- package/skills/sk:debug/lib/__init__.py +1 -0
- package/skills/sk:debug/lib/bug_gatherer.py +55 -0
- package/skills/sk:debug/lib/context_reader.py +139 -0
- package/skills/sk:debug/lib/findings_writer.py +76 -0
- package/skills/sk:debug/lib/lessons_writer.py +165 -0
- package/skills/sk:debug/lib/step_runner.py +326 -0
- package/skills/sk:features/SKILL.md +238 -0
- package/skills/sk:frontend-design/LICENSE.txt +177 -0
- package/skills/sk:frontend-design/SKILL.md +191 -0
- package/skills/sk:laravel-init/SKILL.md +37 -0
- package/skills/sk:laravel-new/SKILL.md +68 -0
- package/skills/sk:lint/SKILL.md +113 -0
- package/skills/sk:perf/LICENSE.txt +177 -0
- package/skills/sk:perf/SKILL.md +188 -0
- package/skills/sk:release/SKILL.md +113 -0
- package/skills/sk:release/references/android-checklist.md +269 -0
- package/skills/sk:release/references/ios-checklist.md +339 -0
- package/skills/sk:release/release.sh +378 -0
- package/skills/sk:review/SKILL.md +346 -0
- package/skills/sk:review/references/security-checklist.md +223 -0
- package/skills/sk:schema-migrate/SKILL.md +125 -0
- package/skills/sk:schema-migrate/orms/drizzle.md +546 -0
- package/skills/sk:schema-migrate/orms/laravel.md +367 -0
- package/skills/sk:schema-migrate/orms/prisma.md +357 -0
- package/skills/sk:schema-migrate/orms/rails.md +351 -0
- package/skills/sk:schema-migrate/orms/sqlalchemy.md +385 -0
- package/skills/sk:schema-migrate/references/detection.md +110 -0
- package/skills/sk:setup-claude/SKILL.md +365 -0
- package/skills/sk:setup-claude/references/detection.md +6 -0
- package/skills/sk:setup-claude/references/templates.md +11 -0
- package/skills/sk:setup-claude/scripts/apply_setup_claude.py +443 -0
- package/skills/sk:setup-claude/scripts/detect_arch_changes.py +437 -0
- package/skills/sk:setup-claude/templates/.claude/docs/arch-changelog-guide.md.template +6 -0
- package/skills/sk:setup-claude/templates/.claude/docs/changelog-guide.md.template +12 -0
- package/skills/sk:setup-claude/templates/CHANGELOG.md.template +21 -0
- package/skills/sk:setup-claude/templates/CLAUDE.md.template +299 -0
- package/skills/sk:setup-claude/templates/arch-changelog-guide.md.template +3 -0
- package/skills/sk:setup-claude/templates/changelog-guide.md.template +3 -0
- package/skills/sk:setup-claude/templates/commands/brainstorm.md.template +74 -0
- package/skills/sk:setup-claude/templates/commands/execute-plan.md.template +57 -0
- package/skills/sk:setup-claude/templates/commands/features.md.template +238 -0
- package/skills/sk:setup-claude/templates/commands/finish-feature.md.template +155 -0
- package/skills/sk:setup-claude/templates/commands/plan.md.template +30 -0
- package/skills/sk:setup-claude/templates/commands/re-setup.md.template +38 -0
- package/skills/sk:setup-claude/templates/commands/release.md.template +74 -0
- package/skills/sk:setup-claude/templates/commands/security-check.md.template +172 -0
- package/skills/sk:setup-claude/templates/commands/status.md.template +17 -0
- package/skills/sk:setup-claude/templates/commands/write-plan.md.template +34 -0
- package/skills/sk:setup-claude/templates/finish-feature.md.template +3 -0
- package/skills/sk:setup-claude/templates/plan.md.template +3 -0
- package/skills/sk:setup-claude/templates/status.md.template +3 -0
- package/skills/sk:setup-claude/templates/tasks/findings.md.template +19 -0
- package/skills/sk:setup-claude/templates/tasks/lessons.md.template +26 -0
- package/skills/sk:setup-claude/templates/tasks/progress.md.template +20 -0
- package/skills/sk:setup-claude/templates/tasks/security-findings.md.template +5 -0
- package/skills/sk:setup-claude/templates/tasks/todo.md.template +26 -0
- package/skills/sk:setup-claude/templates/tasks/workflow-status.md.template +31 -0
- package/skills/sk:setup-claude/templates/tasks-findings.md.template +3 -0
- package/skills/sk:setup-claude/templates/tasks-lessons.md.template +3 -0
- package/skills/sk:setup-claude/templates/tasks-progress.md.template +3 -0
- package/skills/sk:setup-claude/templates/tasks-todo.md.template +3 -0
- package/skills/sk:setup-claude/tests/test_apply_setup_claude.py +193 -0
- package/skills/sk:setup-optimizer/SKILL.md +184 -0
- package/skills/sk:setup-optimizer/lib/__init__.py +24 -0
- package/skills/sk:setup-optimizer/lib/detect.py +205 -0
- package/skills/sk:setup-optimizer/lib/discover.py +221 -0
- package/skills/sk:setup-optimizer/lib/enrich.py +163 -0
- package/skills/sk:setup-optimizer/lib/merge.py +277 -0
- package/skills/sk:setup-optimizer/lib/sidecar.py +129 -0
- package/skills/sk:setup-optimizer/optimize_claude.py +174 -0
- package/skills/sk:setup-optimizer/templates/CLAUDE.md.template +105 -0
- package/skills/sk:skill-creator/LICENSE.txt +202 -0
- package/skills/sk:skill-creator/SKILL.md +479 -0
- package/skills/sk:skill-creator/agents/analyzer.md +274 -0
- package/skills/sk:skill-creator/agents/comparator.md +202 -0
- package/skills/sk:skill-creator/agents/grader.md +223 -0
- package/skills/sk:skill-creator/assets/eval_review.html +146 -0
- package/skills/sk:skill-creator/eval-viewer/generate_review.py +471 -0
- package/skills/sk:skill-creator/eval-viewer/viewer.html +1325 -0
- package/skills/sk:skill-creator/references/schemas.md +430 -0
- package/skills/sk:skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/skills/sk:skill-creator/scripts/generate_report.py +326 -0
- package/skills/sk:skill-creator/scripts/improve_description.py +248 -0
- package/skills/sk:skill-creator/scripts/package_skill.py +136 -0
- package/skills/sk:skill-creator/scripts/quick_validate.py +103 -0
- package/skills/sk:skill-creator/scripts/run_eval.py +310 -0
- package/skills/sk:skill-creator/scripts/run_loop.py +332 -0
- package/skills/sk:skill-creator/scripts/utils.py +47 -0
- package/skills/sk:smart-commit/SKILL.md +175 -0
- package/skills/sk:test/SKILL.md +171 -0
- package/skills/sk:write-tests/SKILL.md +195 -0
- package/skills/sk:write-tests/references/patterns.md +209 -0
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
# /schema-migrate — Laravel + Eloquent Analysis (Phases 2–5)
|
|
2
|
+
|
|
3
|
+
> This file is loaded by `SKILL.md` when Laravel ORM is detected.
|
|
4
|
+
> Execute Phase 2 through Phase 5 below, then return the final report.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Phase 2: Classify Changes
|
|
9
|
+
|
|
10
|
+
### Files to Scan (read in parallel)
|
|
11
|
+
|
|
12
|
+
1. **`composer.json`** — framework and package versions
|
|
13
|
+
- Confirm `laravel/framework` version
|
|
14
|
+
- Check for `doctrine/dbal` (required for column renames on MySQL < 8.0)
|
|
15
|
+
|
|
16
|
+
2. **`.env`** — environment config
|
|
17
|
+
- Extract `DB_CONNECTION`: `mysql` | `pgsql` | `sqlite`
|
|
18
|
+
- Extract `DB_HOST`, `DB_DATABASE` for context
|
|
19
|
+
|
|
20
|
+
3. **`config/database.php`** — database configuration
|
|
21
|
+
- Fallback if `.env` unreadable
|
|
22
|
+
- Read `default` connection key
|
|
23
|
+
|
|
24
|
+
4. **`database/migrations/*.php`** — migration files
|
|
25
|
+
- List all files sorted by timestamp
|
|
26
|
+
- Read the most recent migration(s) for pending changes
|
|
27
|
+
|
|
28
|
+
5. **`app/Models/`** — Eloquent model files
|
|
29
|
+
- Check `$table`, `$casts`, `$fillable`, `$guarded` properties
|
|
30
|
+
- Identify models affected by pending migration changes
|
|
31
|
+
|
|
32
|
+
6. **`git diff HEAD -- database/migrations/`** — uncommitted migration changes
|
|
33
|
+
|
|
34
|
+
7. **`git log --oneline -5 -- database/migrations/`** — recent migration commit history
|
|
35
|
+
|
|
36
|
+
### Dialect Detection
|
|
37
|
+
|
|
38
|
+
From `.env` `DB_CONNECTION` or `config/database.php`:
|
|
39
|
+
|
|
40
|
+
| Value | Dialect |
|
|
41
|
+
|-------|---------|
|
|
42
|
+
| `mysql` | MySQL |
|
|
43
|
+
| `pgsql` | PostgreSQL |
|
|
44
|
+
| `sqlite` | SQLite |
|
|
45
|
+
| `sqlsrv` | SQL Server |
|
|
46
|
+
|
|
47
|
+
Default if undetectable: MySQL
|
|
48
|
+
|
|
49
|
+
### Risk Matrix
|
|
50
|
+
|
|
51
|
+
| Change | Risk | Notes |
|
|
52
|
+
|--------|------|-------|
|
|
53
|
+
| Add new table (`Schema::create`) | 🟢 Safe | Additive — no existing data affected |
|
|
54
|
+
| Add nullable column (`->nullable()`) | 🟢 Safe | Standard additive change |
|
|
55
|
+
| Add index (`->index()`) | 🟢 Safe | Non-blocking for most engines |
|
|
56
|
+
| Add column with default (`->default(value)`) | 🟡 Careful | Existing rows get default value — verify acceptability |
|
|
57
|
+
| Add unique index (`->unique()`) | 🟡 Careful | Fails if duplicate values exist |
|
|
58
|
+
| Add FK constraint | 🟡 Careful | Orphan row check required; MySQL online DDL |
|
|
59
|
+
| Add NOT NULL column without default | 🔴 Breaking | Existing rows have no value → migration fails |
|
|
60
|
+
| Change column type (`->change()`) | 🔴 Breaking | MySQL online DDL; SQLite: table recreation required |
|
|
61
|
+
| Drop column (`->dropColumn()`) | 🔴 Breaking | Check model `$casts`, `$fillable`, queries |
|
|
62
|
+
| Drop table (`Schema::drop`) | 🔴 Breaking | Check all model references and FK constraints |
|
|
63
|
+
| Rename column (`->renameColumn()`) | 🔴 Breaking | Requires `doctrine/dbal` on MySQL < 8.0 |
|
|
64
|
+
| Rename table (`Schema::rename`) | 🟡 Careful | Update model `$table` property and any hardcoded references |
|
|
65
|
+
|
|
66
|
+
### Also Detect
|
|
67
|
+
|
|
68
|
+
- ⚠️ **Missing `down()` method**: Migration has empty `down()` — rollback silently does nothing
|
|
69
|
+
- ⚠️ **Missing `Schema::disableForeignKeyConstraints()`**: MySQL drops with FK constraints will fail without this wrapper
|
|
70
|
+
- ⚠️ **SQLite ALTER TABLE limitations**: SQLite does not support most column modifications — requires table recreation
|
|
71
|
+
- ⚠️ **Missing `doctrine/dbal`**: `renameColumn()` / `change()` on MySQL < 8.0 requires this package
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Phase 3: Present Risk Report
|
|
76
|
+
|
|
77
|
+
### Report Format
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
81
|
+
/schema-migrate — Schema Change Analysis
|
|
82
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
83
|
+
|
|
84
|
+
ORM: Laravel + Eloquent
|
|
85
|
+
Dialect: MySQL 8.0+
|
|
86
|
+
Workflow: php artisan migrate (versioned migrations)
|
|
87
|
+
Migrations dir: database/migrations/
|
|
88
|
+
Last migration: 2025_02_28_120000_add_applied_notes_to_jobs_table
|
|
89
|
+
|
|
90
|
+
Status:
|
|
91
|
+
📁 Migration files: COMMITTED
|
|
92
|
+
📝 Pending: 1 uncommitted migration
|
|
93
|
+
🔧 doctrine/dbal: INSTALLED ✅
|
|
94
|
+
|
|
95
|
+
Detected Changes (since last commit):
|
|
96
|
+
──────────────────────────────────────────
|
|
97
|
+
|
|
98
|
+
🟢 SAFE (1 change)
|
|
99
|
+
• jobs: Added nullable column `applied_notes` (text, nullable)
|
|
100
|
+
|
|
101
|
+
🟡 CAREFUL (1 change — review before migrating)
|
|
102
|
+
• profile: Added column `email` (string, NOT NULL, default: '')
|
|
103
|
+
↳ All existing rows will get empty string value
|
|
104
|
+
↳ Is '' an acceptable default? Consider nullable first.
|
|
105
|
+
|
|
106
|
+
🔴 BREAKING (1 change — stop and read migration plan)
|
|
107
|
+
• jobs: Column `job_type` changed from string → integer
|
|
108
|
+
↳ MySQL online DDL will attempt MODIFY COLUMN
|
|
109
|
+
↳ Review for silent truncation or cast failures
|
|
110
|
+
↳ Test with --pretend first
|
|
111
|
+
|
|
112
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Dialect-Specific Notes
|
|
116
|
+
|
|
117
|
+
#### MySQL
|
|
118
|
+
- ✅ Online DDL available in MySQL 8.0+ (ALGORITHM=INPLACE for many operations)
|
|
119
|
+
- ⚠️ `renameColumn()` and `change()` require `doctrine/dbal` on MySQL < 8.0
|
|
120
|
+
- ⚠️ FK drops require `Schema::disableForeignKeyConstraints()` wrapper
|
|
121
|
+
- ⚠️ Strict mode warnings: large table defaults may trigger metadata lock
|
|
122
|
+
|
|
123
|
+
#### PostgreSQL
|
|
124
|
+
- ✅ Full ALTER TABLE support — most changes are online
|
|
125
|
+
- ✅ Column type changes generally safe with implicit casts
|
|
126
|
+
- ⚠️ Long-running ALTER may briefly lock large tables
|
|
127
|
+
|
|
128
|
+
#### SQLite
|
|
129
|
+
- 🚨 Cannot rename columns or change column types directly
|
|
130
|
+
- 🚨 Must recreate table via raw SQL in migration (see Scenario below)
|
|
131
|
+
- ✅ All other additive changes work normally
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Phase 4: Per-Change Migration Plans
|
|
136
|
+
|
|
137
|
+
### Scenario: Add NOT NULL Column Without Default
|
|
138
|
+
|
|
139
|
+
```
|
|
140
|
+
Problem: Existing rows have no value for the new column → migration fails.
|
|
141
|
+
|
|
142
|
+
Safe path (nullable-first deploy):
|
|
143
|
+
Step 1: Create migration with nullable column
|
|
144
|
+
$table->string('email')->nullable();
|
|
145
|
+
php artisan migrate
|
|
146
|
+
|
|
147
|
+
Step 2: Backfill existing rows
|
|
148
|
+
DB::table('users')->whereNull('email')->update(['email' => '']);
|
|
149
|
+
# Or use a separate data migration
|
|
150
|
+
|
|
151
|
+
Step 3: Create second migration to add NOT NULL constraint
|
|
152
|
+
$table->string('email')->nullable(false)->change();
|
|
153
|
+
php artisan migrate
|
|
154
|
+
|
|
155
|
+
Alternative (with default — single migration):
|
|
156
|
+
$table->string('email')->default('');
|
|
157
|
+
php artisan migrate
|
|
158
|
+
⚠️ All existing rows get '' — verify this is acceptable
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
### Scenario: Rename Column
|
|
164
|
+
|
|
165
|
+
```
|
|
166
|
+
Check doctrine/dbal requirement:
|
|
167
|
+
MySQL < 8.0: composer require doctrine/dbal --dev
|
|
168
|
+
MySQL 8.0+: Native rename support (no doctrine/dbal needed)
|
|
169
|
+
PostgreSQL: Native rename support
|
|
170
|
+
SQLite: Not supported — requires table recreation (see below)
|
|
171
|
+
|
|
172
|
+
Migration:
|
|
173
|
+
$table->renameColumn('old_name', 'new_name');
|
|
174
|
+
|
|
175
|
+
After migrating:
|
|
176
|
+
✅ Update model $casts, $fillable, $guarded arrays
|
|
177
|
+
✅ Search codebase for 'old_name' string references
|
|
178
|
+
✅ Update any API resources / form requests referencing the old name
|
|
179
|
+
|
|
180
|
+
Zero-downtime rename (for production with live traffic):
|
|
181
|
+
Step 1: Add new column (nullable): $table->string('new_name')->nullable();
|
|
182
|
+
Step 2: Deploy code that writes to both old_name AND new_name
|
|
183
|
+
Step 3: Backfill: UPDATE table SET new_name = old_name WHERE new_name IS NULL;
|
|
184
|
+
Step 4: Deploy code that reads from new_name only
|
|
185
|
+
Step 5: Remove old_name column in final migration
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
### Scenario: SQLite Destructive Change (Column Type / Rename)
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
SQLite does not support ALTER COLUMN — must recreate the table.
|
|
194
|
+
|
|
195
|
+
Migration template using raw SQL:
|
|
196
|
+
public function up(): void
|
|
197
|
+
{
|
|
198
|
+
// 1. Create new table with desired schema
|
|
199
|
+
DB::statement('CREATE TABLE users_new (
|
|
200
|
+
id INTEGER PRIMARY KEY,
|
|
201
|
+
name TEXT NOT NULL,
|
|
202
|
+
new_column INTEGER NOT NULL DEFAULT 0, -- changed type
|
|
203
|
+
created_at DATETIME,
|
|
204
|
+
updated_at DATETIME
|
|
205
|
+
)');
|
|
206
|
+
|
|
207
|
+
// 2. Copy data from old table
|
|
208
|
+
DB::statement('INSERT INTO users_new (id, name, new_column, created_at, updated_at)
|
|
209
|
+
SELECT id, name, CAST(old_column AS INTEGER), created_at, updated_at
|
|
210
|
+
FROM users');
|
|
211
|
+
|
|
212
|
+
// 3. Drop old table
|
|
213
|
+
Schema::drop('users');
|
|
214
|
+
|
|
215
|
+
// 4. Rename new table
|
|
216
|
+
DB::statement('ALTER TABLE users_new RENAME TO users');
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
public function down(): void
|
|
220
|
+
{
|
|
221
|
+
// Reverse the process with original schema
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
### Scenario: Missing `down()` Method
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
Problem: Laravel's rollback calls down() — if it's empty, rollback silently does nothing.
|
|
231
|
+
|
|
232
|
+
Detection: Check if down() is empty (just {}) or missing.
|
|
233
|
+
|
|
234
|
+
Template for correct down() methods:
|
|
235
|
+
|
|
236
|
+
// For: $table->string('new_column')
|
|
237
|
+
// Down should be:
|
|
238
|
+
public function down(): void
|
|
239
|
+
{
|
|
240
|
+
Schema::table('users', function (Blueprint $table) {
|
|
241
|
+
$table->dropColumn('new_column');
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// For: Schema::create('new_table', ...)
|
|
246
|
+
// Down should be:
|
|
247
|
+
public function down(): void
|
|
248
|
+
{
|
|
249
|
+
Schema::dropIfExists('new_table');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// For: $table->renameColumn('old', 'new')
|
|
253
|
+
// Down should be:
|
|
254
|
+
public function down(): void
|
|
255
|
+
{
|
|
256
|
+
Schema::table('users', function (Blueprint $table) {
|
|
257
|
+
$table->renameColumn('new', 'old');
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
### Scenario: FK Constraint Ordering Issue
|
|
265
|
+
|
|
266
|
+
```
|
|
267
|
+
Detection: A migration creates a FK reference to a table that is created
|
|
268
|
+
in a LATER migration file (by timestamp).
|
|
269
|
+
|
|
270
|
+
Example:
|
|
271
|
+
2025_01_01_000000_create_posts_table.php → references users.id
|
|
272
|
+
2025_01_01_000001_create_users_table.php → creates users table
|
|
273
|
+
|
|
274
|
+
This will fail because posts FK references users before users exists.
|
|
275
|
+
|
|
276
|
+
Fix options:
|
|
277
|
+
Option A: Rename migration files to fix timestamp ordering
|
|
278
|
+
- Change 2025_01_01_000000_create_posts_table.php to a later timestamp
|
|
279
|
+
|
|
280
|
+
Option B: Split FK creation into separate migration
|
|
281
|
+
- Create posts table without FK first
|
|
282
|
+
- Add FK in a third migration after users table migration
|
|
283
|
+
|
|
284
|
+
Option C: Add FK in the users migration
|
|
285
|
+
- After creating users table, add FK to posts in same migration file
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
---
|
|
289
|
+
|
|
290
|
+
## Phase 5: Command Recommendations
|
|
291
|
+
|
|
292
|
+
### Core Commands
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
# Check migration status
|
|
296
|
+
php artisan migrate:status
|
|
297
|
+
|
|
298
|
+
# Run pending migrations
|
|
299
|
+
php artisan migrate
|
|
300
|
+
|
|
301
|
+
# Preview SQL without executing (dry run)
|
|
302
|
+
php artisan migrate --pretend
|
|
303
|
+
|
|
304
|
+
# Rollback last batch of migrations
|
|
305
|
+
php artisan migrate:rollback --step=1
|
|
306
|
+
|
|
307
|
+
# Roll back a specific migration
|
|
308
|
+
php artisan migrate:rollback --step=1
|
|
309
|
+
|
|
310
|
+
# Roll back to specific migration version
|
|
311
|
+
php artisan migrate:down --path=database/migrations/[filename].php
|
|
312
|
+
|
|
313
|
+
# Check current migration version
|
|
314
|
+
php artisan migrate:status
|
|
315
|
+
|
|
316
|
+
# Create a new migration file
|
|
317
|
+
php artisan make:migration [describe_change] --table=[table_name]
|
|
318
|
+
php artisan make:migration create_[table_name]_table
|
|
319
|
+
|
|
320
|
+
# Reset all migrations and re-run (dev only — DESTRUCTIVE)
|
|
321
|
+
php artisan migrate:fresh
|
|
322
|
+
php artisan migrate:fresh --seed # with seeders
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Workflow: Development
|
|
326
|
+
|
|
327
|
+
```bash
|
|
328
|
+
# 1. Review pending migrations
|
|
329
|
+
/schema-migrate
|
|
330
|
+
|
|
331
|
+
# 2. Preview SQL (dry run)
|
|
332
|
+
php artisan migrate --pretend
|
|
333
|
+
|
|
334
|
+
# 3. If SQL looks correct, apply
|
|
335
|
+
php artisan migrate
|
|
336
|
+
|
|
337
|
+
# 4. Verify status
|
|
338
|
+
php artisan migrate:status
|
|
339
|
+
|
|
340
|
+
# 5. Commit
|
|
341
|
+
git add database/migrations/
|
|
342
|
+
git commit -m "feat(schema): [describe change]"
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Workflow: MySQL — Column Changes
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
# Check doctrine/dbal for rename/change operations
|
|
349
|
+
composer show doctrine/dbal # must be installed for MySQL < 8.0
|
|
350
|
+
|
|
351
|
+
# Preview change
|
|
352
|
+
php artisan migrate --pretend
|
|
353
|
+
|
|
354
|
+
# Apply
|
|
355
|
+
php artisan migrate
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Workflow: SQLite — Destructive Changes
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
# SQLite: always use raw SQL for column type changes or renames
|
|
362
|
+
# See Scenario: SQLite Destructive Change above
|
|
363
|
+
|
|
364
|
+
# After writing raw SQL migration:
|
|
365
|
+
php artisan migrate --pretend # verify SQL output
|
|
366
|
+
php artisan migrate # apply
|
|
367
|
+
```
|