@jumpgroup/laravel-tools 3.3.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.
Files changed (78) hide show
  1. package/.claude/settings.local.json +59 -0
  2. package/README.md +378 -0
  3. package/bin/groups/cache.js +52 -0
  4. package/bin/groups/database.js +105 -0
  5. package/bin/groups/forge.js +272 -0
  6. package/bin/groups/local.js +78 -0
  7. package/bin/groups/media.js +110 -0
  8. package/bin/tools.js +23 -0
  9. package/docs/Changelog.md +267 -0
  10. package/docs/TODO.md +167 -0
  11. package/docs/releases/release_0.0.1.md +116 -0
  12. package/docs/releases/release_0.0.2.md +88 -0
  13. package/docs/releases/release_0.0.3.md +58 -0
  14. package/docs/releases/release_0.0.4.md +128 -0
  15. package/docs/releases/release_0.0.5.md +77 -0
  16. package/docs/releases/release_0.0.6.md +80 -0
  17. package/docs/releases/release_1.0.0.md +61 -0
  18. package/docs/releases/release_1.0.1.md +18 -0
  19. package/docs/releases/release_1.0.2.md +18 -0
  20. package/docs/releases/release_1.0.3.md +19 -0
  21. package/docs/releases/release_1.1.0.md +18 -0
  22. package/docs/releases/release_1.1.1.md +17 -0
  23. package/docs/releases/release_1.1.2.md +18 -0
  24. package/docs/releases/release_1.1.3.md +21 -0
  25. package/docs/releases/release_1.1.4.md +18 -0
  26. package/docs/releases/release_1.1.5.md +18 -0
  27. package/docs/releases/release_1.1.6.md +21 -0
  28. package/docs/releases/release_1.1.7.md +17 -0
  29. package/docs/releases/release_2.0.0.md +192 -0
  30. package/docs/releases/release_2.0.1.md +53 -0
  31. package/docs/releases/release_2.0.2.md +55 -0
  32. package/docs/releases/release_2.0.3.md +69 -0
  33. package/docs/releases/release_2.1.0.md +59 -0
  34. package/docs/releases/release_2.2.0.md +83 -0
  35. package/docs/releases/release_2.2.1.md +36 -0
  36. package/docs/releases/release_2.2.2.md +57 -0
  37. package/docs/releases/release_2.2.3.md +39 -0
  38. package/docs/releases/release_2.2.4.md +75 -0
  39. package/docs/releases/release_2.2.5.md +69 -0
  40. package/docs/releases/release_3.0.0.md +87 -0
  41. package/docs/releases/release_3.0.1.md +65 -0
  42. package/docs/releases/release_3.1.0.md +90 -0
  43. package/docs/releases/release_3.2.0.md +74 -0
  44. package/docs/releases/release_3.3.0.md +72 -0
  45. package/package.json +35 -0
  46. package/src/aws/bucket.js +287 -0
  47. package/src/aws/cloudfront.js +433 -0
  48. package/src/aws/config.js +39 -0
  49. package/src/aws/iam.js +189 -0
  50. package/src/cache.js +49 -0
  51. package/src/database.js +315 -0
  52. package/src/forge/client.js +43 -0
  53. package/src/forge/config.js +33 -0
  54. package/src/forge/provisioning.js +191 -0
  55. package/src/forge/servers.js +27 -0
  56. package/src/forge/sites.js +93 -0
  57. package/src/google/groupMembers.js +35 -0
  58. package/src/google/utilities.js +39 -0
  59. package/src/local/doctor.js +214 -0
  60. package/src/local/setup.js +398 -0
  61. package/src/media.js +143 -0
  62. package/src/stub/docker/mysql/my.cnf +6 -0
  63. package/src/stub/docker/php/local.ini +4 -0
  64. package/src/stub/docker/traefik/dynamic_conf.yml +4 -0
  65. package/src/stub/docker/traefik/traefik.yml +24 -0
  66. package/src/stub/docker-compose/php8.0/docker-compose.yml +78 -0
  67. package/src/stub/docker-compose/php8.1/docker-compose.yml +78 -0
  68. package/src/stub/docker-compose/php8.2/docker-compose.yml +78 -0
  69. package/src/stub/docker-compose/php8.3/docker-compose.yml +78 -0
  70. package/src/stub/docker-compose/php8.4/docker-compose.yml +78 -0
  71. package/src/stub/docker-compose.yml +78 -0
  72. package/src/utilities/command.js +137 -0
  73. package/src/utilities/dateUtils.js +7 -0
  74. package/src/utilities/fileUtils.js +36 -0
  75. package/src/utilities/google-drive.js +69 -0
  76. package/src/utilities/pathUtils.js +15 -0
  77. package/src/utilities/userInput.js +28 -0
  78. package/src/utilities/utilities.js +57 -0
@@ -0,0 +1,267 @@
1
+ # Changelog
2
+
3
+ All releases are documented in detail in `docs/releases/`.
4
+
5
+ ---
6
+
7
+ ## [3.3.0] — 2026-04-24
8
+ ### Added
9
+ - Nuovo comando `forge server delete`: seleziona un server Forge e lo elimina con prompt distruttivo (default N)
10
+ ### Changed
11
+ - Convenzione domini aggiornata al prefisso `api.` in tutti gli ambienti:
12
+ - Locale: `api.{appName}.test` (era `{appName}.test`) — certificati SSL, `/etc/hosts`, `APP_URL`, `ASSETS_URL`
13
+ - `forge site create`: dominio pre-compilato con `api.{appName}.sitointest.it` (staging) o `api.{appName}.it` (production), modificabile dall'utente
14
+ ### Fixed
15
+ - Import mancante di `select` in `bin/groups/forge.js` causava crash in `forge site create` al passo selezione provider Git
16
+
17
+ ## [3.2.1] — 2026-04-24
18
+ ### Changed
19
+ - `forge site create` aggiunge automaticamente `php artisan migrate --force` al deploy script quando il server è di tipo staging (nome contiene "staging")
20
+ - Le migrazioni su production restano manuali via UI Forge
21
+
22
+ ## [3.2.0] — 2026-04-24
23
+ ### Added
24
+ - Nuovo comando `forge site create`: crea un sito Laravel su un server Forge esistente e installa il repository Git
25
+ - Selezione provider Git (GitHub/GitLab/Bitbucket), repository (`org/repo`) e branch
26
+ - Nome database suggerito da `APP_NAME`, PHP version da `composer.json`
27
+ - Polling fino a `status=installed` (ogni 5s, timeout 5 min) poi install repo + composer automatico
28
+ - Output riepilogo con hint passi successivi (`forge env set` → `forge deploy`)
29
+ - `createSite`, `pollSiteInstalled`, `installGitRepo` in `src/forge/sites.js`
30
+
31
+ ## [3.1.0] — 2026-04-24
32
+ ### Added
33
+ - Nuovo comando `forge server create`: provisioning server AWS Lightsail tramite Forge API
34
+ - Auto-incremento nome server per pattern blue/green (`myapp-staging` → `myapp-staging-2` → ...) con conferma prima di procedere
35
+ - Lettura versione PHP da `composer.json` per allineamento automatico locale/remoto
36
+ - Selezione regione (eu-central-1 / us-west-2), piano Lightsail e Redis opzionale
37
+ - Polling provisioning con progress dots (ogni 20s, timeout 25 min)
38
+ - `src/forge/provisioning.js`: `getAwsCredential`, `getSizesForRegion`, `readPhpVersionFromComposer`, `resolveServerName`, `createServer`, `pollServerReady`
39
+
40
+ ## [3.0.1] — 2026-04-23
41
+ ### Fixed
42
+ - `getServerPath` legge ora il campo `path` da `laravel-tools.yml` invece di derivarlo dall'`APP_NAME` con il path Deployer errato (`/var/www/{app}/current`)
43
+ - Errore esplicito se `path` manca dalla configurazione dell'ambiente
44
+ - `cache flush-remote` passava `appName` invece di `env` a `getServerPath`
45
+ ### Changed
46
+ - `getServerPath` spostato da `pathUtils.js` a `command.js` (stessa fonte: `laravel-tools.yml`)
47
+
48
+ ## [3.0.0] — 2026-04-23
49
+ ### Added
50
+ - Nuovo gruppo comandi `forge`: integrazione con Laravel Forge API (nuova `/api`, non legacy `/api/v1`)
51
+ - `forge token set` — salva il token in `~/.laravel-tools`
52
+ - `forge servers` — elenca i server dell'account
53
+ - `forge deploy` — seleziona server/sito e avvia deploy
54
+ - `forge env get` / `forge env set` — legge/sovrascrive il `.env` remoto (set con prompt distruttivo in rosso)
55
+ - `forge logs` — stampa il log dell'ultimo deploy
56
+ - `src/forge/` — client HTTP nativo (`fetch`), config globale, server e site helpers
57
+
58
+ ## [2.2.5] — 2026-04-23
59
+
60
+ ### Added
61
+ - `executeCommandWithOutput` utility in `command.js`: cattura stdout/stderr e li include nel messaggio di errore in caso di exit code non-zero
62
+ - Health check Laravel post-setup via `php artisan about` alla fine di `local setup-laravel`
63
+ - Recovery automatico senza Filament: `composer install`, `package:discover`, `storage:link`, `optimize:clear` + secondo tentativo di health check
64
+ - Log di conferma `✅ Bootstrap Laravel verificato.` al termine del health check riuscito
65
+ ### Changed
66
+ - `runLaravelHealthCheck` usa `executeCommandWithOutput`: l'output artisan è ora visibile negli errori
67
+ - `runNoFilamentRecovery` include ora anche `storage:link` nel flusso di recovery
68
+ - Errori post-health check ora in italiano con output artisan allegato (sia per Filament che per recovery fallito)
69
+
70
+ ## [2.2.4] — 2026-04-08
71
+ ### Added
72
+ - `getBucketOriginDomainCandidates()` e `getDistributionForProjectStrict()` in `cloudfront.js`: lookup deterministico vincolato a origin S3 + tag/comment con gestione esplicita dei duplicati
73
+ - Campo `originDomainNames` nei row CloudFront per supportare il match sull'origin
74
+ ### Fixed
75
+ - `resolveOrCreateDistributionForProject` usa ora `getDistributionForProjectStrict` invece di `getDistributionByProjectTagStrict`, eliminando il rischio di creare distribuzioni duplicate
76
+ - `getDistributionsByProjectTag` aggiunge fallback su `comment` quando il tag lookup AWS è temporaneamente non disponibile; lancia errore esplicito se il lookup fallisce completamente
77
+ - `PutObjectCommand` in `bucket.js`: `Body` ora è `Buffer.alloc(0)` invece di stringa vuota per compatibilità aws-sdk
78
+
79
+ ## [2.2.3] — 2026-04-08
80
+ ### Fixed
81
+ - `getOriginAccessControlByName` in `cloudfront.js`: corretto crash causato da discrepanza tra la shape degli oggetti OAC nel listing AWS e quella restituita dalla creazione; i campi sono ora normalizzati esplicitamente
82
+
83
+ ## [2.2.2] — 2026-04-08
84
+ ### Added
85
+ - `src/google/groupMembers.js`: `getMembersOfGroupEmail()` per recupero membri da API Gmail Group Alias interna
86
+ - `src/google/utilities.js`: `getLocalKeys()` e `getPeopleName()` per lettura credenziali `.secret-fetcher` e lookup dinamico nomi team
87
+ ### Changed
88
+ - `getUserName()` in `utilities.js`: aggiunta conferma opzionale prima della selezione, recupero dinamico dei nomi team via API con fallback sulla lista locale
89
+ - Lista `TEAM_MEMBERS` aggiornata: aggiunti `anto` e `giulia`
90
+
91
+ ## [2.2.1] — 2026-04-08
92
+ ### Changed
93
+ - Aggiunta documentazione mancante per versioni `2.1.0` e `2.2.0`: release note e voci Changelog
94
+
95
+ ## [2.2.0] — 2026-04-08
96
+ ### Added
97
+ - New `local doctor` command to run a fast diagnostic of the local Laravel project state
98
+ ### Checks
99
+ - Presence/availability checks for key files: `.env.example`, `.secret-fetcher`, `.env`, `docker-compose.yml`, local cert files, `laravel-tools.yml`
100
+ - Minimal `.env.example` key validation (`APP_NAME`, `APP_URL`, `ASSETS_URL`, DB credentials)
101
+ - Local dependency checks (`docker compose`, `mkcert`, `composer`, `sudo`)
102
+ - Docker daemon reachability and `${APP_NAME}-api` / `${APP_NAME}-mysql` container status
103
+ ### Behavior
104
+ - Doctor output is grouped as `ok`, `warning`, `fail`
105
+ - Command exits with non-zero status when blocking failures are detected
106
+
107
+ ## [2.1.0] — 2026-04-08
108
+ ### Changed
109
+ - Database command group hardened for safer operational usage on local and remote flows
110
+ ### Added
111
+ - `--dry-run` support on:
112
+ `database remote-export`, `database local-import`, `database local-export`, `database remote-import`
113
+ ### Fixed
114
+ - `database remote-import` now asks explicit confirmation before import
115
+ - `database remote-import` now asks whether to create a pre-import remote backup
116
+ - On remote import failure, rollback guidance is printed when backup was created
117
+ - Post-import remote DB health check (`SELECT 1`) added before final success
118
+ - Remote temporary dump cleanup now depends on successful import completion
119
+
120
+ ## [2.0.3] — 2026-04-07
121
+ ### Changed
122
+ - Reduced unnecessary AWS API usage during media dry-runs
123
+ ### Fixed
124
+ - Dry-run distribution setup now skips strict CloudFront lookup and goes straight through the simulated creation path
125
+ - Dry-run IAM setup no longer resolves the real CloudFront distribution when no ID was provided
126
+ - Media dry-runs now use a deterministic simulated CloudFront ID when needed, avoiding avoidable read calls during preview-only execution
127
+
128
+ ## [2.0.2] — 2026-04-07
129
+ ### Fixed
130
+ - Corrected another dry-run edge case in media IAM setup
131
+ - Dry-run access key generation now behaves coherently when the target IAM user does not exist yet, avoiding an unnecessary `ListAccessKeys` call path
132
+ - `media setup-iam` / full media setup dry-runs now return deterministic placeholder credentials for brand-new users instead of tripping over real IAM key listing logic
133
+
134
+ ## [2.0.1] — 2026-04-07
135
+ ### Fixed
136
+ - Corrected a dry-run glitch in CloudFront bucket policy setup
137
+ - `applyCloudFrontReadPolicy(...)` now exits before performing AWS reads/writes when `dryRun` is enabled
138
+ - Media dry-runs no longer attempt to fetch or mutate the current S3 bucket policy before the dry-run short-circuit
139
+
140
+ ## [2.0.0] — 2026-04-07
141
+ ### Added
142
+ - New `media` command group for AWS media infrastructure management
143
+ - `media setup-general` to provision or reconcile the full media stack for a project:
144
+ S3 bucket, CloudFront distribution, bucket read policy and IAM user credentials
145
+ - `media setup-iam` to create or rotate the dedicated media IAM user credentials
146
+ - S3 inspection helpers:
147
+ `media s3 list`, `media s3 get`
148
+ - CloudFront inspection/setup helpers:
149
+ `media cloudfront list`, `media cloudfront get`, `media cloudfront setup`
150
+ - AWS account resolution via STS to build CloudFront-scoped S3 bucket policies
151
+ ### Changed
152
+ - `local setup-project` now optionally offers AWS media stack setup after updating project identity
153
+ - `.env.example` can now be enriched with media-related values during setup:
154
+ `AWS_DEFAULT_REGION`, `AWS_BUCKET`, `AWS_URL`, `CLOUDFRONT_DISTRIBUTION_ID`, `CLOUDFRONT_DOMAIN`, `S3_SITE_BUCKET`, `S3_UPLOADS_BUCKET_URL`
155
+ ### Security
156
+ - Media storage is configured as a private S3 bucket behind CloudFront Origin Access Control (OAC)
157
+ - Bucket policies are now merged/idempotent so reruns preserve unrelated statements while ensuring CloudFront read access
158
+ - IAM access key rotation for the media user is now safe: new key first, old key removed only after successful creation
159
+
160
+ ## [1.1.7] — 2026-04-02
161
+ ### Added
162
+ - `local setup-laravel` now runs `php artisan filament:assets` after Filament installation, so generated panels have their assets published immediately
163
+
164
+ ## [1.1.6] — 2026-04-02
165
+ ### Changed
166
+ - `local setup-laravel` now runs Laravel migrations with `php artisan migrate --graceful`
167
+ ### Fixed
168
+ - Session-table migration detection was stabilized before running migrations, reducing false positives around `create_sessions_table`
169
+
170
+ ## [1.1.5] — 2026-04-02
171
+ ### Fixed
172
+ - Filament installation during `local setup-laravel` now uses `--no-interaction`, removing self-spam / interactive noise during setup
173
+
174
+ ## [1.1.4] — 2026-04-02
175
+ ### Fixed
176
+ - Session migration detection now uses `readdirSync` on `database/migrations` instead of `glob`, making the check more reliable in local setup
177
+
178
+ ## [1.1.3] — 2026-04-02
179
+ ### Added
180
+ - `local setup-repo` now ensures `mysql/` and `docker/certs/` are added to the target project's `.gitignore` when missing
181
+ ### Changed
182
+ - Composer dependency installation is now executed explicitly during `local setup-repo`, keeping output ordered and visible in the setup flow
183
+ ### Fixed
184
+ - Session-table generation logic was hardened before running migrations
185
+
186
+ ## [1.1.2] — 2026-04-02
187
+ ### Added
188
+ - New `local user add` command to create a Filament user in the running `${APP_NAME}-api` container
189
+
190
+ ## [1.1.1] — 2026-04-02
191
+ ### Fixed
192
+ - Corrected the Composer package constraint used when requiring `filament/filament` during setup
193
+
194
+ ## [1.1.0] — 2026-04-02
195
+ ### Added
196
+ - `local setup-laravel` now optionally offers Filament installation during Laravel bootstrap
197
+
198
+ ## [1.0.3] — 2026-04-02
199
+ ### Added
200
+ - `local setup-repo` can now append missing local artifact folders to the target project's `.gitignore`
201
+
202
+ ## [1.0.2] — 2026-04-02
203
+ ### Fixed
204
+ - `local setup-laravel` now generates the session migration when needed before running Laravel migrations
205
+
206
+ ## [1.0.1] — 2026-04-02
207
+ ### Fixed
208
+ - Corrected stub-copy target handling in `local setup-repo`, preventing the repo root from being treated as a file during `replaceFiles`
209
+
210
+ ## [1.0.0] — 2026-04-02
211
+ ### Added
212
+ - Documented the recommended multi-repo Codex workflow for working across `laravel-tools`, a Laravel boilerplate repo, and a real Laravel reference project
213
+ - Added `local setup-project` to define the local project identity before preparing the repo
214
+ ### Changed
215
+ - Local Laravel workflow now documented as 4 explicit steps:
216
+ `npx laravel-tools local setup-project` -> `yarn repo-setup` -> `yarn start` -> `yarn setup-laravel`
217
+ - `local setup-project` now prompts for the project name, normalizes it, and updates `APP_NAME`, `APP_URL` and `ASSETS_URL` in `.env.example`
218
+ - `local setup-repo` now focuses on local environment preparation and adds both `${APP_NAME}.test` and `mail.${APP_NAME}.test` to `/etc/hosts`
219
+ - Traefik Docker stubs updated from `v2.11` to `v3.6.11` now that the previously known macOS compatibility issue is resolved
220
+ - Traefik static config updated alongside the v3 move so generated local environments use the validated v3 baseline
221
+ - MySQL local stub now sets `max_allowed_packet = 256M` and leaves `general_log` disabled by default
222
+ - Docker Compose stubs now prefer Laravel-native `DB_DATABASE`, while CLI database operations remain compatible with legacy `DB_NAME`
223
+ - Database import flow now clears all four Laravel caches (`cache`, `config`, `route`, `view`) for consistency with the `cache` command group
224
+ ### Fixed
225
+ - Missing `.secret-fetcher` during `local setup-project` now fails immediately with the standardized message:
226
+ `Secret fetcher non è inizializzato, contattare Giada o Andrea`
227
+
228
+ ## [0.0.6] — 2026-03-20
229
+ ### Added
230
+ - Mailpit (`axllent/mailpit:latest`) added to all Docker Compose stubs as local mail service
231
+ - Mailpit accessible via SMTP on port `1025` and web UI on `mail.{APP_NAME}.test` via Traefik
232
+ ### Replaced
233
+ - Mailhog (unmaintained since 2021) not added — went straight to Mailpit as the maintained alternative
234
+
235
+ ## [0.0.5] — 2026-03-20
236
+ ### Added
237
+ - PHP version stub variants: `docker-compose/php8.0` through `php8.4`
238
+ - `--phpversion` flag on `local setup-repo` to select the Docker image
239
+ ### Changed
240
+ - `traefik` updated `v2.4.7` → `v2.11` (stayed on v2 for consistency with existing projects)
241
+ - `mysql` updated `8.0` → `8.4`
242
+ - `jumpgroupit/laravel-image` updated `0.1.0` → `0.2.5` (PHP 8.4, latest)
243
+
244
+ ## [0.0.4] — 2026-03-18
245
+ ### Added
246
+ - `local` command group: `setup-repo`, `setup-laravel`
247
+ - Docker stub files for Laravel (`docker-compose.yml`, traefik, php.ini, my.cnf)
248
+ - Dependencies: `@jumpgroup/secret-fetcher`, `glob`, `hostile`
249
+ ### Fixed
250
+ - Container names corrected across `cache` and `database` modules:
251
+ `{APP_NAME}-app` → `{APP_NAME}-api`, `{APP_NAME}-db` → `{APP_NAME}-mysql`
252
+
253
+ ## [0.0.3] — 2026-03-18
254
+ ### Added
255
+ - `cache` command group: `flush-local`, `flush-remote`, `flush-all`
256
+ - Clears Laravel caches (`cache:clear`, `config:clear`, `route:clear`, `view:clear`) locally via Docker and remotely via SSH
257
+
258
+ ## [0.0.2] — 2026-03-18
259
+ ### Added
260
+ - `database` command group: `remote-export`, `local-import`, `local-export`, `remote-import`, `list`
261
+ - Google Drive integration for dump storage (via OS keyring)
262
+
263
+ ## [0.0.1] — 2026-03-18
264
+ ### Added
265
+ - Project scaffolding: `package.json`, `.gitignore`, `bin/tools.js` entry point
266
+ - All shared utilities: `command`, `dateUtils`, `fileUtils`, `google-drive`, `pathUtils`, `userInput`, `utilities`
267
+ - Server connection config via `laravel-tools.yml` (host + SSH user per environment)
package/docs/TODO.md ADDED
@@ -0,0 +1,167 @@
1
+ # TODO
2
+
3
+ This file tracks implementation work that is still pending in `laravel-tools`.
4
+
5
+ ---
6
+
7
+ ## Remote Environments (Staging/Production)
8
+
9
+ ### Why this is needed
10
+
11
+ `database remote-export` and `database remote-import` already exist, but they rely on
12
+ remote connection metadata (`host`, `user`) that is not generated by any server setup
13
+ flow in `laravel-tools`.
14
+
15
+ In `trellis-tools`, this gap is solved by `server setup`, which creates/reuses servers
16
+ and updates local config files used by remote commands.
17
+
18
+ Current `laravel-tools` state:
19
+ - remote DB scripts are present
20
+ - remote server creation lifecycle is missing
21
+ - companion file updates are missing
22
+
23
+ ---
24
+
25
+ ## What is already done
26
+
27
+ - `database remote-export` implemented
28
+ - `database remote-import` implemented
29
+ - `database local-export` implemented
30
+ - `database local-import` implemented
31
+ - remote import hardening added:
32
+ - confirm prompt before import
33
+ - optional pre-import backup prompt
34
+ - rollback command shown on failure
35
+ - post-import DB health check (`SELECT 1`)
36
+ - cache clear after import
37
+ - dry-run support
38
+
39
+ ---
40
+
41
+ ## Missing elements for full remote lifecycle
42
+
43
+ ### 1) Server setup command group (new)
44
+
45
+ - Add a `server` command group in `laravel-tools`
46
+ - Add `server setup` command for company flow (`staging`, `production`)
47
+ - Scope first implementation to Lightsail only
48
+ - Region support aligned with team usage (`eu-central-1`, `eu-west-1`)
49
+
50
+ Acceptance criteria:
51
+ - command can create or reuse a server for selected env
52
+ - command returns public IP and instance metadata
53
+ - command is safe on reruns
54
+
55
+ ### 2) Remote metadata persistence (required by DB/cache scripts)
56
+
57
+ - Establish one canonical project file for remote metadata:
58
+ - `laravel-tools.yml`
59
+ - Ensure it contains:
60
+ - `staging.host`
61
+ - `staging.user`
62
+ - `production.host`
63
+ - `production.user`
64
+ - `server setup` must update this file automatically after provisioning or IP change
65
+
66
+ Acceptance criteria:
67
+ - no manual IP copy needed after server setup
68
+ - remote DB/cache commands work immediately after setup
69
+
70
+ ### 3) Server companion actions (minimal parity with trellis workflow)
71
+
72
+ - SSH readiness check after creation
73
+ - Optional static IP association flow
74
+ - Minimal firewall baseline (SSH + HTTPS; optional team ports)
75
+ - Optional DNS/SMTP hooks should be deferred to a later phase unless explicitly requested
76
+
77
+ Acceptance criteria:
78
+ - server can be reached via SSH with configured user
79
+ - rerun does not duplicate or corrupt existing infra state
80
+
81
+ ### 4) Runtime validations in remote commands
82
+
83
+ - Keep strict env handling (`staging`, `production`)
84
+ - Improve error quality when `laravel-tools.yml` is missing/incomplete
85
+ - Add explicit preflight in remote database/cache commands:
86
+ - verify `host` and `user` for selected env
87
+ - fail with actionable message
88
+
89
+ Acceptance criteria:
90
+ - failure messages tell exactly what key is missing and where
91
+
92
+ ### 5) Documentation and release notes
93
+
94
+ - Add `Server` command documentation in `docs/commands` equivalent structure used by repo
95
+ - Update README with remote environment lifecycle:
96
+ - create server
97
+ - auto-write `laravel-tools.yml`
98
+ - run remote DB/cache commands
99
+ - Add release notes for the new server lifecycle feature
100
+
101
+ Acceptance criteria:
102
+ - a new dev can setup remote env without tribal knowledge
103
+
104
+ ---
105
+
106
+ ## Suggested implementation order
107
+
108
+ 1. Add `server setup` skeleton + CLI wiring
109
+ 2. Implement Lightsail create/reuse flow
110
+ 3. Implement `laravel-tools.yml` upsert writer
111
+ 4. Add preflight checks in remote database/cache flows
112
+ 5. Add static IP/firewall baseline
113
+ 6. Write docs and release notes
114
+
115
+ ---
116
+
117
+ ## Explicitly out of scope for this phase
118
+
119
+ - Compressed DB dumps (`.sql.gz`)
120
+ - Dynamic arbitrary environments beyond company-standard `staging` and `production`
121
+ - Full Trellis-level DNS/SES automation in first pass
122
+ - EC2 parity before Lightsail flow is stable
123
+
124
+ ---
125
+
126
+ ## Backlog (low priority)
127
+
128
+ - `media setup-alias-cloudfront`
129
+ - Purpose: attach `media.<domain>` alias + ACM cert + DNS record to an existing CloudFront distribution
130
+ - Status: deferred (currently considered low value compared to server lifecycle and remote workflow foundations)
131
+
132
+ - `certificate` command group (ACM)
133
+ - Purpose: request/get/delete ACM certificates and automate DNS validation records when needed
134
+ - Typical use: prerequisite for CloudFront aliases/custom domains
135
+ - Status: deferred
136
+
137
+ - `smtp setup` command group (SES/SNS)
138
+ - Purpose: automate transactional email setup for project environments
139
+ - Expected scope:
140
+ - create/verify SES identity for project domain/subdomain
141
+ - generate SMTP credentials (IAM-backed)
142
+ - optionally wire SNS notifications for bounce/complaint visibility
143
+ - push resulting config/secrets into project env + `.secret-fetcher`
144
+ - Impact:
145
+ - removes repetitive manual AWS Console setup
146
+ - reduces go-live risk from missing DNS/auth configuration
147
+ - standardizes mail setup across `staging` and `production`
148
+ - Status: deferred
149
+
150
+ - `budget` command group (AWS Budgets)
151
+ - Purpose: project-level cost governance from CLI
152
+ - Expected scope:
153
+ - list/get/create/update/delete budgets
154
+ - optional bulk cleanup by project tag/pattern
155
+ - email alert thresholds for monthly spend
156
+ - Impact:
157
+ - adds spending visibility and alerts per project
158
+ - reduces manual AWS console operations for budget management
159
+ - Status: deferred
160
+
161
+ ---
162
+
163
+ ## Open decisions (to confirm before coding server setup)
164
+
165
+ - Default SSH user to write in `laravel-tools.yml` (`deployer` vs other)
166
+ - Whether static IP should be mandatory or optional by default
167
+ - Whether server setup should always be interactive or support a fully scripted mode
@@ -0,0 +1,116 @@
1
+ # Release 0.0.1 — Project scaffolding & utilities
2
+
3
+ **Date:** 2026-03-18
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ First commit. Establishes the project structure and all shared utility modules
10
+ that every future command group will depend on. No commands are usable yet —
11
+ this is the foundation layer.
12
+
13
+ The architecture mirrors `@jumpgroup/trellis-tools` exactly: a `bin/` layer for
14
+ CLI definitions only (Commander.js), and a `src/` layer for all business logic.
15
+
16
+ ---
17
+
18
+ ## Files added
19
+
20
+ ### `package.json`
21
+ Defines the package as `@jumpgroup/laravel-tools`. Entry point is `bin/tools.js`,
22
+ exposed as the `laravel-tools` binary. Only the dependencies needed so far are
23
+ included — more will be added as command groups are built.
24
+
25
+ ### `.gitignore`
26
+ Mirrors trellis-tools. Excludes: `node_modules/`, `.env`, `docker/`,
27
+ `docker-compose.yml`, `.secret-fetcher`, `.laravel-tools`, `laravel-tools.yml`.
28
+
29
+ ### `bin/tools.js`
30
+ Entry point. Imports all command group modules, registers them with Commander.js,
31
+ calls `program.parse()`. Currently only wires up the `database` group
32
+ (added in 0.0.2).
33
+
34
+ ### `src/utilities/command.js`
35
+ Core execution and config-reading utilities:
36
+ - `executeCommand(command, args, options)` — runs shell commands, streams
37
+ stdout/stderr to the terminal, returns a Promise.
38
+ - `getIp(environment)` — reads server IP from `laravel-tools.yml::{env}.host`.
39
+ In trellis-tools this read from `trellis/hosts/{env}.yml`. Replaced with a
40
+ project-level YAML file that developers fill in manually until `server setup`
41
+ can write it automatically (pending Q1).
42
+ - `getSshUser(environment)` — reads SSH user from `laravel-tools.yml::{env}.user`.
43
+ In trellis-tools this was hardcoded to `web` (a Trellis-provisioned user).
44
+ For Laravel the user depends on how the server is provisioned, so it is
45
+ configurable per environment.
46
+ - `getAppName()` — reads `APP_NAME` from `.env.example`. In trellis-tools this
47
+ also fell back to `wordpress_sites.yml` — not needed for Laravel.
48
+
49
+ **`laravel-tools.yml` format expected by this module:**
50
+ ```yaml
51
+ staging:
52
+ host: 1.2.3.4
53
+ user: deployer
54
+
55
+ production:
56
+ host: 5.6.7.8
57
+ user: deployer
58
+ ```
59
+
60
+ ### `src/utilities/dateUtils.js`
61
+ - `getCurrentDateString()` → `YYYYMMDD` string. Used in database dump filenames.
62
+
63
+ ### `src/utilities/fileUtils.js`
64
+ - `find10LatestFiles(directory, envFilter, usernameFilter)` — lists up to 10
65
+ most recent `.sql` files in a directory, sorted newest-first, with size and
66
+ date metadata. Used by the database command group for dump selection.
67
+ - `filterDatabaseFiles(files, env, username)` — filters a file list by
68
+ environment and optional username token.
69
+
70
+ ### `src/utilities/google-drive.js`
71
+ - `getGoogleDriveDirectory()` — returns the path to the Google Drive shared
72
+ drives folder. Checks the OS keyring first (keytar), then tries to locate the
73
+ folder automatically (Google Drive for Desktop on macOS mounts under
74
+ `~/Library/CloudStorage/GoogleDrive-{email}/`), then prompts the user if not
75
+ found. Saves the result to the keyring so subsequent calls are instant.
76
+ Service name changed from `trellis-tools` to `laravel-tools`.
77
+
78
+ ### `src/utilities/pathUtils.js`
79
+ - `getServerPath(appname)` → `/var/www/{appname}/current`. This is the
80
+ Deployer/Capistrano-style deploy path assumed for Laravel servers. In
81
+ trellis-tools this was `/srv/www/{appname}/current` (set by Trellis).
82
+ **Will be confirmed once Q1 is answered.**
83
+ - `ensureDirectoryExists(path)` — creates a directory recursively if it
84
+ doesn't exist.
85
+ - `resolveDatabasePath(appname, customPath)` — returns
86
+ `{GoogleDriveDirectory}/Tech/DumpsDB/{appname}`. Mirrors trellis-tools exactly.
87
+
88
+ ### `src/utilities/userInput.js`
89
+ - `askYesNo(message)` — confirm prompt via `@inquirer/prompts`.
90
+ - `generateDatabaseFilename(appname, env, date, customName, amsMode, username)`
91
+ — generates the standard dump filename. Mirrors trellis-tools conventions:
92
+ - AMS mode: `{app}_ams{YEAR}_{env}.sql`
93
+ - Standard: `{app}_{env}_{YYYYMMDD}[_{username}].sql`
94
+ - Custom: `{customName}.sql`
95
+
96
+ ### `src/utilities/utilities.js`
97
+ - `checkIfEnvFilesExist()` — asserts `.env.example` is present. Throws with
98
+ the standard Italian error message if not.
99
+ - `getEnvironment()` — interactive `staging` / `production` selector.
100
+ - `getUserName()` — interactive selector for the team member list (used to
101
+ attribute dump filenames). List is hardcoded: `giada`, `andre`, `meg`,
102
+ `betta`, `erica`, `chris`, `simo`, `pier`. Includes a "Nessuno" option to
103
+ skip attribution.
104
+ - `generateRandomPassword(length)` — alphanumeric random password generator.
105
+
106
+ ---
107
+
108
+ ## Design decisions
109
+
110
+ - **`laravel-tools.yml` for server config** — replaces the Trellis Ansible
111
+ inventory files. Developers fill it in manually for now. Once Q1 is answered,
112
+ `server setup` will write it automatically.
113
+ - **Laravel env var naming** — uses `DB_USERNAME` and `DB_DATABASE` (Laravel
114
+ defaults) instead of trellis-tools' `DB_USER` and `DB_NAME`.
115
+ - **ES modules throughout** — `"type": "module"` in `package.json`, matching
116
+ trellis-tools.
@@ -0,0 +1,88 @@
1
+ # Release 0.0.2 — Database command group
2
+
3
+ **Date:** 2026-03-18
4
+
5
+ ---
6
+
7
+ ## Overview
8
+
9
+ Implements the full `database` command group — the first fully usable feature
10
+ of laravel-tools. Covers the complete lifecycle of database dumps: export from
11
+ remote, download locally, import locally, export locally, upload and import to
12
+ remote, and list available dumps.
13
+
14
+ Mirrors trellis-tools `database` commands 1:1 in structure and flow, with two
15
+ key adaptations:
16
+ - `wp db export` / `wp db import` (WP-CLI) → `mysqldump` / `mysql` (direct)
17
+ - `wp cache flush` → `php artisan cache:clear` + `config:clear`
18
+
19
+ ---
20
+
21
+ ## Commands added
22
+
23
+ | Command | What it does |
24
+ |---------|-------------|
25
+ | `database remote-export` | SSH to server, mysqldump, scp to local Google Drive, delete remote copy |
26
+ | `database local-import` | Pick a dump from Google Drive, pipe into local Docker MySQL, clear caches |
27
+ | `database local-export` | mysqldump from local Docker MySQL, save to Google Drive |
28
+ | `database remote-import` | Pick a dump, scp to server, mysql import, clear remote caches, delete remote copy |
29
+ | `database list` | List the 10 most recent dumps in Google Drive for this project |
30
+
31
+ All commands support `-e / --environment` (staging/production) and `--ams` flag.
32
+ `remote-export` and `local-export` also support `-n / --name` for a custom filename.
33
+
34
+ ---
35
+
36
+ ## Files added
37
+
38
+ ### `src/database.js`
39
+ Five exported async functions, one per command. Key implementation details:
40
+
41
+ **`remoteDownload` (remote-export)**
42
+ Connects via SSH, runs `source .env && mysqldump` on the server so that DB
43
+ credentials are read from the server's own `.env` — no credentials need to be
44
+ passed from the developer's machine. Downloads via `scp`, then removes the
45
+ remote copy.
46
+
47
+ **`dbLocalImport` (local-import)**
48
+ Reads DB credentials from the local `.env`. Pipes the selected dump file into
49
+ `docker exec -i {APP_NAME}-db mysql` using a shell redirect (`sh -c "... < file"`).
50
+ After import, runs `cache:clear` and `config:clear` via `docker exec {APP_NAME}-app`.
51
+
52
+ **`dbLocalExport` (local-export)**
53
+ Runs `docker exec {APP_NAME}-db mysqldump` via a shell redirect to write the
54
+ output to a file in Google Drive.
55
+
56
+ **`remoteImport` (remote-import)**
57
+ Uploads the selected dump via `scp`, imports it on the server with
58
+ `source .env && mysql`, clears remote Laravel caches via SSH, then removes
59
+ the remote copy.
60
+
61
+ **`listDatabases` (list)**
62
+ Calls `find10LatestFiles` with optional environment filter, prints results to
63
+ the terminal.
64
+
65
+ ### `bin/groups/database.js`
66
+ CLI layer only. Wires the five Commander subcommands to the functions in
67
+ `src/database.js`. No business logic.
68
+
69
+ ### `OPEN_QUESTIONS.md`
70
+ Documents Q1 (deploy tool decision) and the exact files that will need updating
71
+ once the answer is known.
72
+
73
+ ---
74
+
75
+ ## Design decisions
76
+
77
+ - **`source .env` on the server** — the cleanest way to get DB credentials for
78
+ mysqldump without passing them from the developer's machine or hardcoding them.
79
+ Works for standard Laravel `.env` files. Edge cases (special chars in passwords)
80
+ are handled by quoting variables: `-u"$DB_USERNAME"`.
81
+ - **Shell pipe for mysql import** — `docker exec -i` with stdin redirect requires
82
+ `sh -c "... < file"` rather than native spawn piping, for simplicity.
83
+ - **Docker container naming** — `{APP_NAME}-db` for MySQL, `{APP_NAME}-app` for
84
+ the Laravel PHP container. These will be set by the Docker Compose stubs in a
85
+ future release.
86
+ - **AMS mode preserved** — the `--ams` flag is wired through for filename
87
+ convention compatibility, even though AMS-specific database logic is minimal
88
+ for Laravel.