Mejor de media y aun así arriesgado
Una suite de evaluación de agentes une el estado final, el camino y las ejecuciones repetidas en una puerta que un cambio debe pasar. Sirve porque cada comprobación por sí sola deja pasar un cambio malo distinto.
El nuevo agente de la tienda saca 77 por ciento frente a 61. Pero un caso que nunca debe fallar ahora falla a veces.
Al final de esta lección
Nota
Puedo unir trayectoria, estado y ejecuciones repetidas en una sola puerta.
Palabras clave
| Palabra | Qué significa |
|---|---|
| Puerta | una nota de corte fijada antes de la ejecución |
| Caso obligatorio | un caso que nunca puede fallar una ejecución |
| Crecimiento de pasos | cuántos pasos más puede dar la versión nueva |
| Código de salida | el número que devuelve un script, 0 si todo va bien |
| Suite | las comprobaciones que se lanzan juntas en cada cambio |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Cada puerta detecta un cambio distinto
Fija cada puerta antes de ver el resultado. Una dice que el estado final es correcto con suficiente frecuencia. Otra dice que los pasos no han crecido demasiado. Otra nombra los casos obligatorios. Otra dice que el cambio no es claramente peor.
Esto es el crecimiento de pasos: una puerta de coste para un agente, porque cada paso se paga.
Ejemplo resuelto: cuatro puertas
| Puerta | Regla | Qué detecta |
|---|---|---|
| Tasa de estado | al menos 70 por ciento de las ejecuciones acaban bien | una versión que falla demasiado |
| Pasos | no más de 20 por ciento de pasos extra | una versión correcta y lenta |
| Obligatorios | el caso 4 pasa en cada ejecución | una rotura en lo que más importa |
| No peor | la prueba de signos no dice peor | un cambio que arregló poco y rompió mucho |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Una puerta termina en un código de salida
Cada puerta añade su nombre a una lista de fallos. La suite imprime la lista y devuelve un código de salida: 0 cuando la lista está vacía y 1 cuando no.
El laboratorio no tiene integración continua. Una suite real ejecutaría este script en cada cambio y pararía la publicación con un 1.
Escribe las ejecuciones grabadas
docker exec -w /home/node/project agent sh -c "printf '%s\n' '// Tres ejecuciones grabadas de cada caso: [el estado es correcto (1 o 0), pasos dados].' 'const oldVersion = [' ' [[1, 4], [1, 4], [1, 5]], [[1, 5], [0, 6], [1, 5]], [[0, 6], [0, 7], [1, 6]],' ' [[1, 4], [1, 4], [1, 4]], [[1, 5], [1, 5], [0, 5]], [[0, 7], [0, 7], [0, 6]],' '];' 'const newVersion = [' ' [[1, 4], [1, 4], [1, 4]], [[1, 5], [1, 5], [1, 6]], [[1, 6], [0, 7], [1, 6]],' ' [[1, 5], [0, 5], [1, 5]], [[1, 5], [1, 5], [1, 5]], [[0, 7], [1, 7], [0, 7]],' '];' 'const settings = { minState: 70, stepGrowth: 20, must: [3] };' 'module.exports = { oldVersion, newVersion, settings };' > runs.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe la suite, parte 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { oldVersion, newVersion, settings } = require(\"./runs\");' 'function states(version) {' ' return version.map(function (runs) {' ' return runs.filter(function (run) { return run[0] === 1; }).length;' ' });' '}' 'function stateRate(version) {' ' const total = states(version).reduce(function (a, b) { return a + b; }, 0);' ' return Math.floor(total * 100 / (version.length * version[0].length));' '}' 'function steps(version) {' ' let sum = 0;' ' version.forEach(function (runs) { runs.forEach(function (run) { sum = sum + run[1]; }); });' ' return sum;' '}' > suite.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe la suite, parte 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function signP(better, worse) {' ' const n = better + worse;' ' if (n === 0) return 1;' ' let total = 0;' ' let ways = 1;' ' for (let i = 0; i <= Math.min(better, worse); i = i + 1) {' ' total = total + ways;' ' ways = ways * (n - i) / (i + 1);' ' }' ' return Math.min(1, 2 * total / Math.pow(2, n));' '}' 'const before = states(oldVersion);' 'const after = states(newVersion);' 'let better = 0;' 'let worse = 0;' 'before.forEach(function (n, at) {' ' if (after[at] > n) better = better + 1;' ' if (after[at] < n) worse = worse + 1;' '});' >> suite.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe la suite, parte 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const failures = [];' 'const rate = stateRate(newVersion);' 'console.log(\"Tasa de estado \" + rate + \" por ciento, hacen falta \" + settings.minState);' 'if (rate < settings.minState) failures.push(\"tasa de estado\");' 'console.log(\"Pasos \" + steps(newVersion) + \" frente a \" + steps(oldVersion) + \", límite \" + settings.stepGrowth + \" por ciento más\");' 'if (steps(newVersion) * 100 > steps(oldVersion) * (100 + settings.stepGrowth)) failures.push(\"pasos\");' 'const broken = settings.must.filter(function (at) { return after[at] < newVersion[at].length; });' 'console.log(\"Casos obligatorios que fallaron en una ejecución: \" + broken.map(function (at) { return at + 1; }).join(\", \"));' 'if (broken.length > 0) failures.push(\"casos obligatorios\");' >> suite.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Escribe la suite, parte 4
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const p = signP(better, worse);' 'console.log(\"Mejores \" + better + \", peores \" + worse + \", p \" + p.toFixed(3));' 'if (p < 0.05 && worse > better) failures.push(\"peor\");' 'console.log(failures.length === 0 ? \"Todas las puertas pasan\" : \"Puertas fallidas: \" + failures.join(\", \"));' 'process.exit(failures.length === 0 ? 0 : 1);' >> suite.js"Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Lanza la suite y lee su código
docker exec -w /home/node/project agent node suite.js; echo código de salida $?Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Lo que imprime la suite
| Línea | Lo que muestra |
|---|---|
| Tasa de estado | 77 por ciento, hacen falta 70: pasa |
| Pasos | 98 frente a 95, límite 20 por ciento: pasa |
| Casos obligatorios | el caso 4 falló una ejecución |
| Mejores y peores | mejores 4, peores 1, p 0.375: pasa |
| Resultado | Puertas fallidas: casos obligatorios |
| Código de salida | 1 |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Pruébalo
Consejo
En runs.js cambia la segunda ejecución del cuarto caso de newVersion de [0, 5] a [1, 5] y lanza otra vez. La puerta de obligatorios pasa y el código de salida es 0.
Un error frecuente
Advertencia
Mucha gente afloja una puerta cuando un buen cambio no la pasa. Una puerta movida después de un fallo ya no protege nada. Si la puerta era errónea, cámbiala en una revisión aparte, con su razón escrita, y nunca en el mismo cambio que la falló.