Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 15 additions & 12 deletions docs/adr/0014-gradas-de-prueba-y-puerta-de-calidad.md
Original file line number Diff line number Diff line change
Expand Up @@ -492,18 +492,21 @@ Sin lista de ficheros —la etiqueta `ci-full`, más ficheros de los que lista l
PR, 300 en la comparación de un push), un push sin commit anterior o un fallo de la API— corren
todos los carriles de Linux. Un PR sin lista corre también los de plataforma; un push, no.

**Qué concierne a una plataforma** es lo que solo ella compila o lo que cambia cómo se compila
allí: `Cargo.toml`, `Cargo.lock`, `build.rs`, `tauri.conf.json`, `clippy.toml`, el `justfile`,
`versions.env`, `.github/`, los scripts que corren sus jobs (`bootstrap.sh`, `pinned-version.sh`,
`install-tools.sh`) y las reglas mismas; `packaging/windows/` y el manifiesto de Windows solo a
Windows, y `packaging/macos/` solo a macOS. Los ficheros con un `cfg` de plataforma no se
escriben a mano: «Alcance» los calcula en cada ejecución con `scripts/platform-files.sh` sobre un
*sparse checkout* de los `.rs` y se los pasa a `ci-lanes.sh`. Cuenta un `cfg` de `windows`,
`unix`, `target_os` o `target_family` —también `target_os = "linux"`, porque tocar una rama deja
huérfana la otra— y cuenta **el módulo entero** que un `cfg` de plataforma declara con `mod`:
`identity/adapters/windows_store/cng.rs` no lleva ningún `cfg`, y solo compila en Windows. Un
cambio solo en el puente Java no enciende las plataformas: su `.dll` y su `.dylib` las compilan
la nocturna y la entrega.
**Qué concierne a una plataforma** es el código que nombra esa plataforma y lo que cambia cómo
se compila allí: `Cargo.toml`, `build.rs`, `versions.env`, `platforms.yml` y la acción
`setup-runner`, y los scripts que instalan sus herramientas (`bootstrap.sh`, `pinned-version.sh`,
`install-tools.sh`); `packaging/windows/` y el manifiesto de Windows solo a Windows, y
`packaging/macos/` solo a macOS. Los ficheros con un `cfg` de plataforma no se escriben a mano:
«Alcance» los calcula en cada ejecución con `scripts/platform-files.sh` sobre un *sparse
checkout* de los `.rs` y se los pasa a `ci-lanes.sh`, cada uno con su plataforma. Un `cfg` que
nombra `windows` o `not(unix)` es de Windows; uno que nombra `"macos"`, de macOS, y
`not(target_os = "linux")`, de las dos. Cuenta **el módulo entero** que ese `cfg` declara con
`mod`: `identity/adapters/windows_store/cng.rs` no lleva ningún `cfg`, y solo compila en
Windows. Un `cfg` de `unix`, `target_os = "linux"` o `target_family` no enciende ninguna, ni
`Cargo.lock`, `tauri.conf.json`, `clippy.toml`, el `justfile`, el resto de `.github/` o las
reglas mismas: los compila o los prueba Linux, y su efecto en otra plataforma lo ve la nocturna.
Un cambio solo en el puente Java tampoco enciende las plataformas: su `.dll` y su `.dylib` las
compilan la nocturna y la entrega.

**La nocturna es la red.** Una vez al día, si `main` ha cambiado desde la nocturna anterior,
corre Windows y macOS enteros sobre `main`. Si sale roja, abre una issue con `needs-triage`, o
Expand Down
8 changes: 4 additions & 4 deletions docs/agents/code-host-ci.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,10 +159,10 @@ todos. Las guardas de `rfirma-app/src-tauri/tests` leen `rfirma-app/src`,
`testdata/` y el `justfile`, así que un PR solo de interfaz sigue pagando
`Cadena Rust`. La de citas de ADR también lee `docs/adr`, pero ese directorio
no enciende el carril: la guarda corre en local, en el commit y en el push. Windows y macOS van al revés: corren solo si algún
fichero les concierne —los `.rs` con un `cfg` de plataforma y los módulos que
ese `cfg` declara, que `scripts/platform-files.sh` calcula en cada ejecución,
más `Cargo.toml`, `Cargo.lock`, `build.rs`, la configuración de Tauri, su
`packaging/`, el `justfile`, `versions.env` y `.github/`—, y en un push nunca:
fichero les concierne —los `.rs` con un `cfg` que nombra esa plataforma y los
módulos que ese `cfg` declara, que `scripts/platform-files.sh` calcula en cada
ejecución, más `Cargo.toml`, `build.rs`, su `packaging/`, `versions.env`,
`platforms.yml` y `setup-runner`—, y en un push nunca:
los cubre la nocturna (ADR-0014). Las etiquetas `ci-full`, `ci-windows` y
`ci-macos` fuerzan sus carriles en el siguiente push; el resumen de `Alcance`
dice qué corre, qué se omitió y por qué. **Un rojo de Windows o macOS en
Expand Down
4 changes: 2 additions & 2 deletions scripts/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ Los arneses que llaman las recetas del `justfile` (ADR-0013).
| `design_sync_selection.py` | Deriva de los títulos y del `parameters.designSync` de las historias la entrada de design-sync, el `titleMap`, los `overrides`, la tabla de catálogo de `conventions.md` (entre marcadores) (`just design-sync-selection`, antes de cada `/design-sync`; el CI no la verifica). Falla nombrando la historia con capa desconocida, título fuera de convención o componente sin mapear. |
| `token-per-test.sh` | Ejecuta el comando que recibe con una copia privada del almacén de SoftHSM (directorio temporal con su `SOFTHSM2_CONF`, borrado al salir aunque falle), copiada bajo el cerrojo que toma `testdata/softhsm/certs.sh`. Lo llama la receta `coverage` y, como envoltorio de nextest, `.config/nextest.toml` de `rfirma-app/src-tauri`. |
| `ci-lanes.sh` | Dice, a partir de los ficheros de un PR o de un push a `main`, qué carriles del CI tienen que correr, los de Linux y los de Windows y macOS. Lo llama el job `scope` de `ci.yml`, no una receta. |
| `platform-files.sh` | Lista los `.rs` de `rfirma-app/src-tauri` con un `cfg` de plataforma y los módulos que ese `cfg` declara, para `ci-lanes.sh`. Lo llama el job `scope` de `ci.yml`. |
| `platform-files.sh` | Lista, con su plataforma (`windows` o `macos`), los `.rs` de `rfirma-app/src-tauri` con un `cfg` de esa plataforma y los módulos que ese `cfg` declara, para `ci-lanes.sh`. Lo llama el job `scope` de `ci.yml`. |
| `main-moved.sh` | Dice, a partir de las ejecuciones de un workflow, si `main` se ha movido desde la anterior. Lo llaman las puertas de `nightly.yml` y `warm-release-cache.yml`. |
| `packages-manifest.sh` | Escribe y lee el `paquetes.json` de una entrega: una fila por paquete con plataforma, fichero, formato, si es firmable y su aviso; también genera las notas del borrador de la Release. Lo llama la receta `packages-manifest` y lo leen `release.yml`, `preview.yml`, `packaging/verify-packages.sh` y `packaging/repo/`. |
| `preview-comment.sh` | Compone el Markdown del comentario fijo de la preview de una PR a partir de los artefactos, el manifiesto y el contexto de la ejecución; no imprime nada si no hay nada que comentar. Lo llama `preview-comment.yml`. |
| `tests/outline_test.sh` | Prueba el esqueleto, los tramos y el índice que produce `outline.sh` sobre los fixtures de `tests/fixtures/`. |
| `tests/ci_lanes_test.sh` | Prueba qué carriles enciende `ci-lanes.sh` para cada clase de fichero, con la lista de plataforma, en un push y con etiquetas. |
| `tests/platform_files_test.sh` | Prueba `platform-files.sh` sobre un árbol temporal y, contra el repositorio, que el adaptador CNG cuenta como de Windows. |
| `tests/platform_files_test.sh` | Prueba `platform-files.sh` sobre un árbol temporal y, contra el repositorio, que el adaptador CNG cuenta como de Windows y la barra de título de GTK como de ninguna. |
| `tests/main_moved_test.sh` | Prueba `main-moved.sh` con respuestas de la API hechas a mano: primera ejecución, sin cambios, canceladas, otro título y API caída. |
| `tests/packages_manifest_test.sh` | Prueba el manifiesto de paquetes (entrega completa, candidata, extensión desconocida, firmable, plataformas). |
| `tests/preview_comment_test.sh` | Prueba el comentario de la preview: filas por artefacto, avisos del manifiesto, fallo, salida vacía y marcador en la primera línea. |
Expand Down
24 changes: 12 additions & 12 deletions scripts/ci-lanes.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# solo si alguno le concierne. Sin ficheros, corren todos.
#
# Uso: ci-lanes.sh [--platform-files FICHERO] [--no-platforms] [--force windows|macos]...
# --platform-files la salida de scripts/platform-files.sh: rutas exactas y prefijos con '/'
# --platform-files la salida de scripts/platform-files.sh: `plataforma ruta`, exacta o prefijo con '/'
# --no-platforms windows y macos no corren, sean cuales sean los ficheros (push a main)
# --force el carril corre, sean cuales sean los ficheros (etiqueta del PR)
set -euo pipefail
Expand Down Expand Up @@ -104,40 +104,40 @@ native_ignores() {
return 1
}

only_one_platform_compiles() {
local entry
has_cfg_of() {
local platform="$1" file="$2" entry
for entry in "${platform_files[@]}"; do
[ "${entry%% *}" = "$platform" ] || continue
entry="${entry#* }"
case "$entry" in
*/) [[ "$1" == "$entry"* ]] && return 0 ;;
*) [ "$1" = "$entry" ] && return 0 ;;
*/) [[ "$file" == "$entry"* ]] && return 0 ;;
*) [ "$file" = "$entry" ] && return 0 ;;
esac
done
return 1
}

every_platform_needs() {
case "$1" in
rfirma-app/src-tauri/Cargo.toml | rfirma-app/src-tauri/Cargo.lock | rfirma-app/src-tauri/build.rs) return 0 ;;
rfirma-app/src-tauri/tauri.conf.json | rfirma-app/src-tauri/clippy.toml) return 0 ;;
justfile | versions.env | .github/*) return 0 ;;
scripts/ci-lanes.sh | scripts/platform-files.sh) return 0 ;;
rfirma-app/src-tauri/Cargo.toml | rfirma-app/src-tauri/build.rs | versions.env) return 0 ;;
.github/workflows/platforms.yml | .github/actions/setup-runner/*) return 0 ;;
scripts/bootstrap.sh | scripts/pinned-version.sh | scripts/install-tools.sh) return 0 ;;
esac
only_one_platform_compiles "$1"
return 1
}

windows_needs() {
case "$1" in
packaging/windows/* | rfirma-app/src-tauri/windows-app-manifest.xml | rfirma-app/src-tauri/vcpkg.json) return 0 ;;
esac
every_platform_needs "$1"
every_platform_needs "$1" || has_cfg_of windows "$1"
}

macos_needs() {
case "$1" in
packaging/macos/*) return 0 ;;
esac
every_platform_needs "$1"
every_platform_needs "$1" || has_cfg_of macos "$1"
}

lanes=(java web rust native landing)
Expand Down
31 changes: 21 additions & 10 deletions scripts/platform-files.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env bash
# Lista los ficheros de rfirma-app/src-tauri con un cfg de plataforma y, con '/' final, los modulos que solo compila una.
# Lista, como `windows <ruta>` o `macos <ruta>`, los ficheros de rfirma-app/src-tauri con un cfg de esa plataforma y, con '/' final, los modulos que ese cfg declara.
set -euo pipefail

tauri=rfirma-app/src-tauri
Expand All @@ -13,22 +13,33 @@ find "$tauri" -path "$tauri/target" -prune -o -name '*.rs' -type f -print | sort
sub(/\.rs$/, "", file)
return file
}
FNR == 1 { gated = 0; path = ""; dir = FILENAME; sub(/\/[^\/]*$/, "", dir); modules = crate_dir(FILENAME) }
function platforms_of(line, found, off_linux) {
found = ""
off_linux = line ~ /not[(][[:space:]]*target_os[[:space:]]*=[[:space:]]*"linux"[[:space:]]*[)]/
if (off_linux || line ~ /(^|[^A-Za-z0-9_"-])windows([^A-Za-z0-9_"-]|$)/ || line ~ /"windows"/ || line ~ /not[(][[:space:]]*unix[[:space:]]*[)]/) found = found " windows"
if (off_linux || line ~ /"macos"/) found = found " macos"
return found
}
function emit(platforms, path, n, list, i) {
n = split(platforms, list, " ")
for (i = 1; i <= n; i++) print list[i], path
}
FNR == 1 { gated = ""; path = ""; dir = FILENAME; sub(/\/[^\/]*$/, "", dir); modules = crate_dir(FILENAME) }
{
attribute = $0 ~ /^[[:space:]]*#\[/
if ($0 ~ /cfg(!|_attr)?[(](.*[^A-Za-z0-9_"-])?(windows|unix|target_os|target_family)([^A-Za-z0-9_"-]|$)/) {
print FILENAME
if ($0 ~ /^[[:space:]]*#\[cfg[(]/) gated = 1
emit(platforms_of($0), FILENAME)
if ($0 ~ /^[[:space:]]*#\[cfg[(]/) gated = platforms_of($0)
}
if (gated && $0 ~ /^[[:space:]]*#\[path[[:space:]]*=/) {
if (gated != "" && $0 ~ /^[[:space:]]*#\[path[[:space:]]*=/) {
path = $0; sub(/^[^"]*"/, "", path); sub(/".*/, "", path)
}
if (gated && $0 ~ /(^|[][:space:]])mod[[:space:]]+[A-Za-z0-9_]+[[:space:]]*;/) {
if (gated != "" && $0 ~ /(^|[][:space:]])mod[[:space:]]+[A-Za-z0-9_]+[[:space:]]*;/) {
name = $0; sub(/.*(^|[][:space:]])mod[[:space:]]+/, "", name); sub(/[^A-Za-z0-9_].*/, "", name)
if (path != "") print dir "/" path
else { print modules "/" name ".rs"; print modules "/" name "/" }
gated = 0; path = ""; next
if (path != "") emit(gated, dir "/" path)
else { emit(gated, modules "/" name ".rs"); emit(gated, modules "/" name "/") }
gated = ""; path = ""; next
}
if (!attribute && $0 !~ /^[[:space:]]*(\/\/.*)?$/) { gated = 0; path = "" }
if (!attribute && $0 !~ /^[[:space:]]*(\/\/.*)?$/) { gated = ""; path = "" }
}
' | sort -u
25 changes: 15 additions & 10 deletions scripts/tests/ci_lanes_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ work="$(mktemp -d)"
trap 'rm -rf "$work"' EXIT

printf '%s\n' \
rfirma-app/src-tauri/src/desktop/adapters/paths.rs \
rfirma-app/src-tauri/src/identity/adapters/windows_store/ \
"windows rfirma-app/src-tauri/src/desktop/adapters/paths.rs" \
"macos rfirma-app/src-tauri/src/desktop/adapters/paths.rs" \
"windows rfirma-app/src-tauri/src/identity/adapters/windows_store/" \
"macos rfirma-app/src-tauri/src/identity/adapters/macos_store/" \
>"$work/platform-files"

check() {
Expand Down Expand Up @@ -42,18 +44,19 @@ backend="java=false web=false rust=true native=true landing=false"
check "sin ficheros" "$all" "$("$lanes" </dev/null | tr '\n' ' ')"

expect "fichero desconocido" "$linux windows=false macos=false" "lefthook.yml"
expect "justfile" "$all" "justfile"
expect "workflow" "$all" ".github/workflows/ci.yml"
expect "justfile" "$linux windows=false macos=false" "justfile"
expect "workflow" "$linux windows=false macos=false" ".github/workflows/ci.yml"
expect "workflow de plataformas" "$all" ".github/workflows/platforms.yml"
expect "accion local" "$all" ".github/actions/setup-runner/action.yml"
expect "prosa inerte" "$none" "README.md" "docs/research/x.md" "rfirma-conformance/src/main.rs"
expect "interfaz" "java=false web=true rust=true native=false landing=false windows=false macos=false" "rfirma-app/src/App.tsx"
expect "backend" "$backend windows=false macos=false" "rfirma-app/src-tauri/src/lib.rs"
expect "capacidad de tauri" "java=false web=true rust=true native=true landing=false windows=false macos=false" "rfirma-app/src-tauri/capabilities/site.json"
expect "candado de version" "java=false web=true rust=true native=true landing=false windows=true macos=true" "rfirma-app/src-tauri/Cargo.toml"
expect "candado de dependencias" "java=false web=true rust=true native=true landing=false windows=true macos=true" "rfirma-app/src-tauri/Cargo.lock"
expect "candado de dependencias" "java=false web=true rust=true native=true landing=false windows=false macos=false" "rfirma-app/src-tauri/Cargo.lock"
expect "script de compilacion" "$backend windows=true macos=true" "rfirma-app/src-tauri/build.rs"
expect "configuracion de tauri" "java=false web=true rust=true native=true landing=false windows=true macos=true" "rfirma-app/src-tauri/tauri.conf.json"
expect "reglas de clippy" "$backend windows=true macos=true" "rfirma-app/src-tauri/clippy.toml"
expect "configuracion de tauri" "java=false web=true rust=true native=true landing=false windows=false macos=false" "rfirma-app/src-tauri/tauri.conf.json"
expect "reglas de clippy" "$backend windows=false macos=false" "rfirma-app/src-tauri/clippy.toml"
expect "manifiesto de windows" "java=false web=true rust=true native=true landing=false windows=true macos=false" "rfirma-app/src-tauri/windows-app-manifest.xml"
expect "manifiesto de vcpkg" "java=false web=true rust=true native=true landing=false windows=true macos=false" "rfirma-app/src-tauri/vcpkg.json"
expect "empaquetado de windows" "java=false web=true rust=false native=false landing=false windows=true macos=false" "packaging/windows/tauri.windows.json"
Expand All @@ -68,8 +71,8 @@ expect "bootstrap" "java=true web=true rust=false native=true landing=false wind
expect "lector de versiones" "java=true web=true rust=true native=true landing=false windows=true macos=true" "scripts/pinned-version.sh"
expect "instalador de herramientas" "java=false web=true rust=true native=true landing=false windows=true macos=true" "scripts/install-tools.sh"
expect "versiones fijadas" "java=true web=true rust=true native=true landing=true windows=true macos=true" "versions.env"
expect "las propias reglas" "$all" "scripts/ci-lanes.sh"
expect "la lista de plataforma" "java=false web=true rust=false native=true landing=false windows=true macos=true" "scripts/platform-files.sh"
expect "las propias reglas" "$linux windows=false macos=false" "scripts/ci-lanes.sh"
expect "la lista de plataforma" "java=false web=true rust=false native=true landing=false windows=false macos=false" "scripts/platform-files.sh"
expect "otro script" "java=false web=true rust=false native=true landing=false windows=false macos=false" "scripts/token-per-test.sh"
expect "site-driver" "java=false web=true rust=true native=true landing=false windows=false macos=false" "testdata/site-driver/driver.mjs"
expect "kit fnmt" "java=true web=false rust=true native=true landing=false windows=false macos=false" "testdata/fnmt/README.md"
Expand All @@ -86,8 +89,10 @@ expect "la union de dos" "java=false web=true rust=true native=true landing=fals
platforms="--platform-files $work/platform-files"
expect_with "fichero con cfg de plataforma" "$backend windows=true macos=true" "$platforms" \
"rfirma-app/src-tauri/src/desktop/adapters/paths.rs"
expect_with "modulo que solo compila una plataforma" "$backend windows=true macos=true" "$platforms" \
expect_with "modulo que solo compila windows" "$backend windows=true macos=false" "$platforms" \
"rfirma-app/src-tauri/src/identity/adapters/windows_store/cng.rs"
expect_with "modulo que solo compila macos" "$backend windows=false macos=true" "$platforms" \
"rfirma-app/src-tauri/src/identity/adapters/macos_store/keychain.rs"
expect_with "prefijo sin su barra" "$backend windows=false macos=false" "$platforms" \
"rfirma-app/src-tauri/src/identity/adapters/windows_store_other.rs"
expect_with "backend sin cfg" "$backend windows=false macos=false" "$platforms" \
Expand Down
Loading
Loading