feat(release): introduce interactive mode
This commit is contained in:
+86
-8
@@ -41,7 +41,11 @@ repositorio.
|
||||
#+BEGIN_SRC text
|
||||
duckbrain-toolbox/
|
||||
bin/duckbrain instalador global (bootstrap)
|
||||
scripts/release escritor único de versión + tag
|
||||
src/autoload.php mapea Toolbox\ -> packages/commands/src/Toolbox/
|
||||
scripts/release version + tag + push (interactivo o directo)
|
||||
scripts/build-phar construye dist/duckbrain.phar autocontenido
|
||||
scripts/publish-phar publica el phar como release en Forgejo
|
||||
Makefile test / build / release / publish / check / clean
|
||||
packages/
|
||||
commands/ cli, migration, toolbox
|
||||
htmx/ htmlComponent, htmx
|
||||
@@ -73,6 +77,25 @@ duckbrain add crypto htmx # copias reales, listas para commitear
|
||||
propios addons sin el instalador global, instala el componente =commands:toolbox=
|
||||
(es un =add= más, no un requisito). A partir de ahí =./duckbrain= funciona solo.
|
||||
|
||||
Alternativa sin clone del repo: descargar el *phar autocontenido* publicado como
|
||||
release y ejecutarlo directamente (los enlaces simbólicos no valen:
|
||||
=self-update= reemplaza el binario con =rename()= sobre su propia ruta):
|
||||
|
||||
#+BEGIN_SRC sh
|
||||
VERSION=$(curl -s https://git.kj2.me/api/v1/repos/kj/duckbrain-toolbox/releases \
|
||||
| jq -r '.[].tag_name' | grep -E '^v[0-9]' | sort -V | tail -1)
|
||||
curl -fsSL "https://git.kj2.me/kj/duckbrain-toolbox/releases/download/$VERSION/duckbrain.phar" \
|
||||
-o ~/.local/bin/duckbrain
|
||||
chmod +x ~/.local/bin/duckbrain
|
||||
|
||||
duckbrain --version # ya es el instalador global; se actualiza solo:
|
||||
duckbrain self-update
|
||||
#+END_SRC
|
||||
|
||||
(Para probar el tuyo local sin release, usa =cp dist/duckbrain.phar ~/.local/bin/duckbrain=
|
||||
en lugar del =curl=; =make build= + =ln -s= solo sirve mientras no llames a
|
||||
=self-update=.)
|
||||
|
||||
* Comandos
|
||||
|
||||
** =duckbrain install [dir]=
|
||||
@@ -212,18 +235,73 @@ desconocida y se fija por commit.
|
||||
|
||||
* Versionado y releases
|
||||
|
||||
Cada paquete se versiona de forma independiente con tags prefijados
|
||||
(=http-v0.1.0=, =crypto-v0.1.0=…). El tag es el descubrimiento; el *commit* es la
|
||||
identidad, así que el lock pinea commits y no se rompe si un tag se mueve.
|
||||
Hay *dos* sistemas de versión y no hay que confundirlos:
|
||||
|
||||
El release lo hace un único script:
|
||||
1. *Paquetes/componentes* — la versión vive en =packages/<paquete>/duckbrain.json= y
|
||||
se versiona de forma independiente con tags prefijados (=http-v0.1.0=,
|
||||
=crypto-v0.1.0=…). La única forma de cambiarla es el asistente:
|
||||
|
||||
#+BEGIN_SRC sh
|
||||
make release # interactivo: elige
|
||||
# paquete e incremento,
|
||||
# muestra cambios
|
||||
# pendientes y confirma
|
||||
scripts/release <paquete> <patch|minor|major> [--yes] # modo directo
|
||||
#+END_SRC
|
||||
|
||||
Bumpea el manifiesto, commitea, crea el tag y lo publica. Al liberar
|
||||
=commands= sincroniza también =Config::VERSION= en el mismo commit. El tag es el
|
||||
descubrimiento; el *commit* es la identidad, así que el lock pinea commits y no
|
||||
se rompe si un tag se mueve. Las versiones retiradas se listan en
|
||||
=yanked.json=; las prereleases se omiten salvo =--pre=. Para detectar bumps
|
||||
olvidados: =git log <paquete>-v<última>..HEAD -- packages/<paquete>= (vacío = al día).
|
||||
|
||||
2. *Instalador/phar* — =Config::VERSION= (=packages/commands/src/Toolbox/Config.php=):
|
||||
es lo que imprime la CLI y la referencia con la que =self-update= compara las
|
||||
releases del servidor. No se edita a mano; la mantiene el release de
|
||||
=commands=. Se publica con =make publish= (ver *Makefile*).
|
||||
|
||||
* Makefile
|
||||
|
||||
=make help= lista los objetivos:
|
||||
|
||||
| Objetivo | Qué hace |
|
||||
|---------------+------------------------------------------------------------|
|
||||
| =make test= | Corre la suite (=php tests/run.php=). En verde antes de commitear. |
|
||||
| =make build= | Genera =dist/duckbrain.phar= + =dist/duckbrain.phar.sha256=. |
|
||||
| =make release= | Asistente interactivo de releases de paquetes (=ARGS="pkg minor --yes"= para modo directo). |
|
||||
| =make publish= | =build= + publica la release =v$(Config::VERSION)= con los assets. Requiere =FORGEJO_TOKEN=. |
|
||||
| =make check= | =self-update --check= contra el servidor: =actual/disponible=, exit 1 si hay nuevo. |
|
||||
| =make clean= | Borra =dist/=. |
|
||||
|
||||
El token para publicar es un token personal de la API de Forgejo
|
||||
(*Ajustes → Aplicaciones*, scope =write:repository=, con caducidad y revocable).
|
||||
Los PAT de Forgejo no pueden limitarse a un solo repositorio: para aislar el
|
||||
riesgo, crea un *usuario bot* con acceso Write solo en =duckbrain-toolbox= y usa
|
||||
su token. =dist/= está en gitignore: nunca se commitea.
|
||||
|
||||
* self-update (el phar)
|
||||
|
||||
#+BEGIN_SRC sh
|
||||
scripts/release <paquete> <patch|minor|major>
|
||||
duckbrain self-update # se auto-reemplaza con la última release
|
||||
duckbrain self-update --check # actual vs disponible (exit 1 si hay nueva)
|
||||
duckbrain self-update --force # reemplaza aunque esté al día
|
||||
#+END_SRC
|
||||
|
||||
Bumpea la versión del manifiesto, commitea, crea el tag y publica. Las versiones
|
||||
retiradas se listan en =yanked.json=; las prereleases se omiten salvo =--pre=.
|
||||
Lee la lista de releases
|
||||
(=https://git.kj2.me/api/v1/repos/kj/duckbrain-toolbox/releases=, sobrescribible
|
||||
con =DUCKBRAIN_UPDATE_URL=) y elige el *mayor tag semver* con la misma clase que
|
||||
el core usa con sus tags; tags que no son semver y drafts se ignoran. No
|
||||
existe la ruta =/releases/latest/download/= en Forgejo, así que no se depende de
|
||||
ella: basta con subir =make publish= la versión real =vX.Y.Z=. La descarga se
|
||||
verifica contra el =.sha256= publicado y el reemplazo es atómico (temp + rename)
|
||||
sobre =Phar::running(false)=. Si =Config::VERSION >= remota= no se descarga nada.
|
||||
|
||||
Para tocar el instalador con el phar en mente: =build-phar= ya ejecuta con
|
||||
=php -d phar.readonly=0= (crear phars está bloqueado por defecto), el código que
|
||||
corre *dentro* del phar no debe usar =glob()= (no soporta el stream =phar://=;
|
||||
usa =DirectoryIterator= / =file_get_contents()=), y la raíz del toolbox se
|
||||
resuelve con =Config::toolboxDir()=, que ya antepone =phar://= cuando toca.
|
||||
|
||||
* Pruebas
|
||||
|
||||
|
||||
Reference in New Issue
Block a user