Skip to content

Commit db058f7

Browse files
committed
release: v0.14.0 — shimkit framework symfony
Sibling framework recipe under the existing `framework` parent. Modelled on the Laravel recipe (v0.7.0), adjusted for Symfony's conventions: Aspect Laravel Symfony ───────────────────────────────────────────────────────────────── Writable tree storage + bootstrap/cache var App secret APP_KEY=base64:... (32B) APP_SECRET=<64 hex> Env file .env (refuses overwrite) .env.local (preserves the framework .env) Console root-level artisan bin/console Scheduler schedule:run every minute no built-in scheduler Surface (one fewer command than Laravel — no cron-install since Symfony has no built-in scheduler): shimkit framework symfony perms PATH [--group G] (MODERATE) shimkit framework symfony env PATH [--name N] [--env E] [--db D] (MODERATE) shimkit framework symfony cache-clear PATH [--env E] shimkit framework symfony console --project PATH [--in-container [--stack NAME]] -- <args> Application-specific Symfony cron entries go via `shimkit cron add` directly. If Symfony Scheduler (the messenger-based approach) gains broad adoption, a cron-install command may land later. `env` writes to `.env.local` rather than `.env` because Symfony's convention is that `.env` ships framework defaults (checked in) and `.env.local` holds gitignored secrets + per-host tweaks. APP_SECRET is hex(32) = 64 chars per the Symfony reference. DATABASE_URL targets shimkit dev DBs by default, with the right URL prefix + serverVersion query parameter for each engine (mysql / mariadb / postgres). Pair with `shimkit db <engine> up` for a working dev setup. `cache-clear` is a thin wrapper around `php bin/console cache:clear --env <env>` for the common case. `console` is the generic passthrough for everything else. Implementation: - New `tools/framework/symfony/` sub-tree (manager + commands + __init__) mirroring `tools/framework/laravel/`. - `framework_app` registers `symfony_app` alongside `laravel_app`. Sub-app surface unchanged for Laravel users. - `FrameworkSymfonyConfig` pydantic model + corresponding `tools.framework.symfony` defaults.json block with `web_group`, `file_mode`, `dir_mode`, `writable_dirs`, `default_env`. Tests: 26 new in test_tools_framework_symfony.py (1044 → 1070 total). Platform gating, perms (path refusal / dry-run / var/ targeting / chgrp skip on missing group / --group override / failed-step JSON), env (overwrite refusal / 64-hex APP_SECRET / default APP_ENV / --env override / DATABASE_URL shape for all three DB engines / dry-run no-write / uniqueness across scaffolds), console (host happy path / missing-php exits 69 / no-args refusal / missing-bin/console refusal / --in-container delegates to StackManager), cache-clear (runs console with --env=<env>), command surface (framework --help lists both recipes; symfony --help lists all four subcommands). Gates: pytest 1070 passed, ruff clean, mypy strict clean. No new optional dependency extras.
1 parent 21e2b70 commit db058f7

13 files changed

Lines changed: 1423 additions & 8 deletions

File tree

CHANGELOG.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,60 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
66

77
## [Unreleased]
88

9+
## [0.14.0] — 2026-05-16
10+
11+
### Added
12+
13+
- `shimkit framework symfony` — sibling framework recipe under the
14+
existing `framework` parent. Four commands:
15+
- `perms PATH [--group G]` (MODERATE) — cross-distro group
16+
detection (same chain as Laravel: `getent` / `dscl` / `grp`);
17+
targets `var/` rather than Laravel's `storage` +
18+
`bootstrap/cache`.
19+
- `env PATH [--name N] [--env E] [--db D]` (MODERATE) —
20+
scaffolds `.env.local` with a generated `APP_SECRET`
21+
(hex(32) — Symfony's documented form). Refuses to overwrite
22+
an existing file. `DATABASE_URL` targets shimkit dev DBs
23+
by default; supports mysql / mariadb / postgres.
24+
- `cache-clear PATH [--env E]` — wraps `php bin/console
25+
cache:clear --env <env>`. Defaults to `dev`.
26+
- `console -- <args>` — passthrough to `php bin/console`. Host
27+
execution by default; `--in-container` routes through
28+
`shimkit stack lemp`.
29+
30+
Symfony has no built-in scheduler like Laravel's
31+
`schedule:run`, so there's no `cron-install` command —
32+
application-specific cron entries go via `shimkit cron add`
33+
directly.
34+
35+
- `tools.framework.symfony` config block with the same shape as
36+
`tools.framework.laravel` plus a `default_env` field (`dev` /
37+
`test` / `prod`).
38+
39+
### Tests
40+
41+
- 26 new tests in `tests/test_tools_framework_symfony.py` (1044 →
42+
1070 total). Platform gating, perms (path refusal / dry-run /
43+
var/ targeting / chgrp skip on missing group / --group override
44+
/ failed-step JSON output), env scaffold (overwrite refusal /
45+
APP_SECRET 64-hex-char shape / default APP_ENV / `--env`
46+
override / DATABASE_URL for all three DB engines including
47+
serverVersion query parameter / dry-run no-write / uniqueness
48+
across two scaffolds), console (host happy path runs `php
49+
bin/console` / missing-php exits 69 / no-args refusal / missing-
50+
bin/console refusal / --in-container delegates to StackManager),
51+
cache-clear (runs console with --env flag), command surface
52+
(framework --help lists symfony alongside laravel; symfony
53+
--help lists all four subcommands).
54+
55+
### Notes
56+
57+
Second framework recipe under the `framework` parent. Future
58+
siblings (`rails`, `django`, `nextjs`) follow the same pattern.
59+
60+
Gates: pytest 1070 passed, ruff clean, mypy strict clean. No new
61+
optional dependency extras.
62+
963
## [0.13.0] — 2026-05-16
1064

1165
### Added

docs/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ shimkit is a collection. Each tool gets its own page:
5858
- **[`shimkit framework laravel`](tools/framework-laravel.md)**
5959
Laravel helpers: perms, `.env` scaffold, scheduler cron-install,
6060
artisan passthrough (host or LEMP container).
61+
- **[`shimkit framework symfony`](tools/framework-symfony.md)**
62+
Symfony helpers: perms (`var/`), `.env.local` scaffold with
63+
`APP_SECRET`, cache-clear, `bin/console` passthrough.
6164

6265
Top-level utilities (not tools):
6366

@@ -91,6 +94,8 @@ Top-level utilities (not tools):
9194

9295
Per-version, user-facing summaries (newest first):
9396

97+
- **[`v0.14.0`](release-notes/v0.14.0.md)** — `shimkit framework
98+
symfony` sibling recipe under the `framework` parent.
9499
- **[`v0.13.0`](release-notes/v0.13.0.md)** — `shimkit tls --method
95100
dns-cloudflare` for DNS-01 + wildcard certs.
96101
- **[`v0.12.0`](release-notes/v0.12.0.md)** — stale-doc cleanup +

docs/release-notes/v0.14.0.md

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# shimkit 0.14.0
2+
3+
`shimkit framework symfony` — sibling recipe under the existing
4+
`framework` parent. Modelled on Laravel (v0.7.0); adjusted for
5+
Symfony's conventions.
6+
7+
For the full machine-readable changelog, see
8+
[`CHANGELOG.md`](../../CHANGELOG.md).
9+
10+
---
11+
12+
## TL;DR
13+
14+
```
15+
shimkit framework symfony perms PATH [--group G] # MODERATE
16+
shimkit framework symfony env PATH [--name N] [--env E] [--db D] # MODERATE
17+
shimkit framework symfony cache-clear PATH [--env E]
18+
shimkit framework symfony console -- <args>
19+
```
20+
21+
Same shape as `framework laravel`, swapping in Symfony's
22+
conventions: writable `var/` (not `storage/` + `bootstrap/cache`),
23+
`APP_SECRET` hex (not `APP_KEY` base64), `bin/console` (not root
24+
`artisan`).
25+
26+
---
27+
28+
## Differences from Laravel
29+
30+
| Aspect | Laravel (v0.7.0) | Symfony (v0.14.0) |
31+
|--------|------------------|-------------------|
32+
| Writable tree | `storage/` + `bootstrap/cache/` | `var/` |
33+
| App secret | `APP_KEY=base64:...` (32 bytes) | `APP_SECRET=...` (hex(32) = 64 chars) |
34+
| Env file | `.env` (gitignored typically) | `.env.local` (gitignored by convention; framework defaults stay in `.env`) |
35+
| Console binary | root-level `artisan` | `bin/console` |
36+
| Scheduler | `php artisan schedule:run` every minute | No built-in scheduler — use `shimkit cron add` directly |
37+
38+
The Symfony recipe is **smaller by one command** (no `cron-install`)
39+
because Symfony doesn't ship a scheduler analogous to Laravel's.
40+
41+
---
42+
43+
## `env` shape
44+
45+
`.env.local` is the gitignored override file; the framework-shipped
46+
`.env` is preserved. Default contents:
47+
48+
```ini
49+
# Symfony local environment overrides (gitignored).
50+
# Framework defaults live in .env; secrets and per-host
51+
# tweaks belong here.
52+
53+
APP_ENV=dev
54+
APP_SECRET=<64 hex chars>
55+
56+
DATABASE_URL="mysql://root:shimkit-dev@127.0.0.1:13306/<dirname>?serverVersion=8.0"
57+
58+
# Mailer — defaults to in-memory; override in prod.
59+
MAILER_DSN=null://null
60+
```
61+
62+
`DATABASE_URL` is engine-aware:
63+
64+
```bash
65+
shimkit framework symfony env --yes --db mysql ./my-app
66+
# → mysql://root:shimkit-dev@127.0.0.1:13306/my-app?serverVersion=8.0
67+
68+
shimkit framework symfony env --yes --db postgres ./my-app
69+
# → postgresql://root:shimkit-dev@127.0.0.1:15432/my-app?serverVersion=16
70+
71+
shimkit framework symfony env --yes --db mariadb ./my-app
72+
# → mysql://root:shimkit-dev@127.0.0.1:13307/my-app?serverVersion=mariadb-10.11
73+
```
74+
75+
Pair with `shimkit db <engine> up` for an end-to-end dev stack.
76+
77+
---
78+
79+
## End-to-end example
80+
81+
```bash
82+
# 1. Start a database
83+
shimkit db postgres up
84+
85+
# 2. Create / clone the Symfony project at ./my-app
86+
87+
# 3. Scaffold env + fix perms
88+
shimkit framework symfony env --yes --db postgres ./my-app
89+
shimkit framework symfony perms --yes ./my-app
90+
91+
# 4. Run migrations + clear cache
92+
shimkit framework symfony console --project ./my-app \
93+
-- doctrine:database:create
94+
shimkit framework symfony console --project ./my-app \
95+
-- doctrine:migrations:migrate --no-interaction
96+
shimkit framework symfony cache-clear --env dev ./my-app
97+
```
98+
99+
---
100+
101+
## Stats
102+
103+
- Tests: 1044 → 1070 (+26)
104+
- Gates: pytest, ruff, mypy strict — all green
105+
- New optional extras: 0
106+
107+
---
108+
109+
## Upgrading
110+
111+
```bash
112+
uv tool upgrade shimkit
113+
pipx upgrade shimkit
114+
```
115+
116+
Laravel users see no behavioural change. To start using the
117+
Symfony recipe, just invoke `shimkit framework symfony --help`.

docs/tools/framework-symfony.md

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# shimkit framework symfony
2+
3+
Symfony-specific helpers. Four commands today. Modelled on the
4+
Laravel recipe — same parent sub-app, same builder pattern, same
5+
host-or-container console passthrough — adjusted for Symfony's
6+
conventions: writable `var/` (not `storage/`), `APP_SECRET` hex
7+
(not `APP_KEY` base64), `bin/console` (not root `artisan`).
8+
9+
## Commands
10+
11+
| Command | Purpose |
12+
|---------|---------|
13+
| `shimkit framework symfony` | Menu. |
14+
| `shimkit framework symfony perms PATH [--group G]` | MODERATE. Fix `var/` permissions. |
15+
| `shimkit framework symfony env PATH [--name N] [--env E] [--db D]` | MODERATE. Scaffold `.env.local` with a generated `APP_SECRET`. |
16+
| `shimkit framework symfony cache-clear PATH [--env E]` | Wraps `php bin/console cache:clear --env <env>`. |
17+
| `shimkit framework symfony console -- <args>` | Passthrough to `bin/console` — host or LEMP container. |
18+
19+
Universal flags before the subcommand (`--quiet`, `--verbose`,
20+
`--log-file`, `--no-color`, `--color`, `--no-input`); per-command
21+
flags after (`--json`, `--dry-run`, `--yes`, `--force`).
22+
23+
## perms
24+
25+
`var/` is the standard Symfony writable tree (covers `cache/`,
26+
`log/`, `sessions/`). Set `tools.framework.symfony.writable_dirs`
27+
in your user config to extend (e.g. `["var", "public/uploads"]`).
28+
29+
```bash
30+
# Default www-data group on Linux
31+
shimkit framework symfony perms --yes ./my-symfony-app
32+
33+
# macOS-friendly group
34+
shimkit framework symfony perms --yes --group staff ./my-symfony-app
35+
36+
# Dry-run plan
37+
shimkit framework symfony perms --dry-run ./my-symfony-app
38+
39+
# JSON (CI / monitoring)
40+
shimkit framework symfony perms --yes --json ./my-symfony-app
41+
```
42+
43+
Group detection: `getent group <name>` on Linux, `dscl . -read
44+
/Groups/<name>` on macOS, `grp.getgrnam()` Python fallback. When
45+
the group doesn't exist on the host, the global `chmod 664` /
46+
`chmod 775` passes still run but `chgrp` is skipped (UI.dim
47+
explains).
48+
49+
## env
50+
51+
Writes `.env.local` with a freshly generated `APP_SECRET`. Symfony's
52+
convention is that **`.env` (checked in) holds framework defaults**
53+
and **`.env.local` (gitignored) holds secrets + per-host tweaks**.
54+
shimkit writes to `.env.local` so the framework-provided `.env`
55+
stays intact.
56+
57+
`APP_SECRET` is `secrets.token_hex(32)` = 64 hex chars — the
58+
[Symfony reference](https://symfony.com/doc/current/reference/configuration/framework.html#secret)
59+
recommends a long random hex.
60+
61+
`DATABASE_URL` defaults target the shimkit dev DBs:
62+
63+
| `--db` | URL prefix | Port | `?serverVersion=` |
64+
|------------|------------|-----:|-------------------|
65+
| `mysql` | `mysql://` | 13306 | `8.0` |
66+
| `mariadb` | `mysql://` | 13307 | `mariadb-10.11` |
67+
| `postgres` | `postgresql://`| 15432 | `16` |
68+
69+
```bash
70+
shimkit db postgres up
71+
shimkit framework symfony env --yes --db postgres ./my-app
72+
shimkit framework symfony console --project ./my-app -- doctrine:migrations:migrate
73+
```
74+
75+
## cache-clear
76+
77+
Wraps `php bin/console cache:clear --env <env>`:
78+
79+
```bash
80+
shimkit framework symfony cache-clear --env dev ./my-app
81+
shimkit framework symfony cache-clear --env prod --in-container --stack myapp ./my-app
82+
```
83+
84+
Default env is `dev` (configurable via
85+
`tools.framework.symfony.default_env`).
86+
87+
## console
88+
89+
Generic passthrough to `bin/console`. Host execution is the
90+
default — preflights `php` via `shimkit.core.version.preflight`,
91+
exits 69 with the remediation hint when `php` is missing.
92+
`--in-container` routes through `shimkit stack lemp`'s php-fpm
93+
container.
94+
95+
```bash
96+
# Host
97+
shimkit framework symfony console --project ./my-app -- about
98+
shimkit framework symfony console --project ./my-app -- doctrine:database:create
99+
100+
# Inside a running LEMP stack
101+
shimkit stack lemp up --project myapp ./my-app
102+
shimkit framework symfony console \
103+
--project ./my-app --in-container --stack myapp \
104+
-- doctrine:migrations:migrate
105+
```
106+
107+
`--project` defaults to the current working directory.
108+
109+
## No cron-install
110+
111+
Symfony doesn't ship a built-in scheduler analogous to Laravel's
112+
`schedule:run`. Application-specific cron entries can be installed
113+
via `shimkit cron add` directly:
114+
115+
```bash
116+
shimkit cron add --yes \
117+
--name my-symfony-nightly \
118+
--schedule "0 3 * * *" \
119+
--cmd "cd /var/www/my-app && php bin/console app:nightly-job >> /dev/null 2>&1"
120+
```
121+
122+
If Symfony Scheduler (the messenger-based approach) gains broad
123+
adoption, a `cron-install` command may land later.
124+
125+
## Configuration
126+
127+
```json
128+
{
129+
"tools": {
130+
"framework": {
131+
"symfony": {
132+
"web_group": "www-data",
133+
"file_mode": "664",
134+
"dir_mode": "775",
135+
"writable_dirs": ["var"],
136+
"default_env": "dev"
137+
}
138+
}
139+
}
140+
}
141+
```
142+
143+
Override `web_group` per host. Add `writable_dirs` entries if your
144+
app writes outside `var/` (e.g. `public/uploads/`).
145+
146+
## Exit codes
147+
148+
| Code | Meaning |
149+
|-----:|---------|
150+
| 0 | success |
151+
| 1 | bad path, missing `bin/console`, refusing overwrite, prompt cancelled |
152+
| 2 | Typer usage error |
153+
| 69 | `EX_UNAVAILABLE` — wrong platform or missing `php` for `console`/`cache-clear` |
154+
| 130 | SIGINT |
155+
156+
## Platform support
157+
158+
| Platform | Status |
159+
|----------|--------|
160+
| macOS | full. Dev account typically owns the project, so `chgrp` is no-op'd unless `--group` is passed. |
161+
| Linux | full. Targets `www-data` by default; override with `--group`. |
162+
| WSL | works (Linux path). |
163+
| Windows | out of charter (use WSL). |

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "shimkit"
7-
version = "0.13.0"
7+
version = "0.14.0"
88
description = "A toolkit of developer utilities — Java version manager, shell upgrader, and more. Python tools, shimmed by bash."
99
readme = "README.md"
1010
license = { file = "LICENSE" }

src/shimkit/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
Python tools, shimmed by bash.
44
"""
55

6-
__version__ = "0.13.0"
6+
__version__ = "0.14.0"
77
__all__ = ["__version__"]

src/shimkit/config/defaults.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,13 @@
207207
"dir_mode": "775",
208208
"writable_dirs": ["storage", "bootstrap/cache"],
209209
"default_cron_schedule": "* * * * *"
210+
},
211+
"symfony": {
212+
"web_group": "www-data",
213+
"file_mode": "664",
214+
"dir_mode": "775",
215+
"writable_dirs": ["var"],
216+
"default_env": "dev"
210217
}
211218
},
212219
"versions": {

0 commit comments

Comments
 (0)