Saltar al contenido principal
DocumentoConstruir flujo de trabajoModularización y reutilización

Modularización y reutilización

sub_workflow, encapsula una parte de la lógica en un módulo, promueve / degrada la reconstrucción con un solo clic, para que ya no sea necesario copiar y pegar el flujo de trabajo uno por uno.

Cuando llegue al segundo y tercer flujo de trabajo, encontrará que cierta lógica aparece repetidamente: extraer datos de ASA, enviar mensajes de Telegram y generar informes de Excel. Si continúa copiando y pegando, tendrá que cambiar tres lugares para cambiar un lugar, la prueba se repetirá y la versión estará fuera de control. Es hora de hacer modularización en este momento.

Plantillas versus módulos nuevamente

Plantilla = una instantánea del documento inicial, que evoluciona de forma independiente después de la clonación; módulo = un subproceso al que se puede hacer referencia, y la persona que llama se beneficiará automáticamente después de la actualización. Los dos no son sustitutos, sino complementarios. Esta página habla de módulos.

¿Qué es un "módulo"?

Un "módulo" es esencialmente un flujo de trabajo que declara los campos de nivel superior de WorkflowModuleContract. Expone además:

  • inputs — Parámetros que la persona que llama debe pasar (con nombre, tipo, requerido, valor predeterminado, descripción)
  • outputs — El resultado estructurado generado después de la ejecución (la persona que llama puede hacer referencia directamente a él)
  • version — Número de versión semántica para facilitar el bloqueo de llamadas
yaml
name: my-team-slack-notifier
version: "1.0.0"

module:
  enabled: true
  inputs:
    webhook_url:
      type: string
      required: true
      description: Slack incoming webhook URL
    channel:
      type: string
      required: false
      default: "#general"
    message:
      type: string
      required: true
    mentions:
      type: array
      items: { type: string }
      required: false
  outputs:
    message_ts:
      type: string
      description: Slack 返回的 message timestamp,可用于后续更新消息
    status:
      type: string
      enum: [sent, failed]

# 模块自己的步骤(内部细节,对调用方黑盒)
steps:
  - id: format_text
    type: code
    language: node
    code: |
      const msg = process.env.WF_VAR_MESSAGE;
      const mentions = JSON.parse(process.env.WF_VAR_MENTIONS || '[]');
      return { text: mentions.map(u => `<@${u}>`).join(' ') + ' ' + msg };

  - id: post
    type: code
    depends_on: [format_text]
    credentials: [slack_oauth]
    code: |
      //  Slack API,返回 message_ts / status 

Después de tener el contrato, el paso sub_workflow de la persona que llama (flujo de trabajo principal):

  • Verificación estática al guardar: las entradas requeridas no se guardarán si falta una;
  • Verificación en tiempo de ejecución: si el tipo no coincide/la enumeración no está en la lista, se informará un error directamente;
  • Autocompletar en el editor: cuando escribe entradas: puede desplazarse hacia abajo para ver qué campos expone el módulo.

Cómo el flujo de trabajo principal llama al módulo

yaml
steps:
  - id: build_report
    type: code
    # ...

  - id: notify
    type: sub_workflow
    module: my-team-slack-notifier    # 引用我们上面定义的模块
    version: "^1.0.0"                  # 锁主版本
    inputs:
      webhook_url: "{{credentials.slack_webhook}}"
      channel: "#ops-alerts"
      message: "日报已生成:{{steps.build_report.data.summary}}"
      mentions: ["U1234", "U5678"]

  - id: record
    type: code
    depends_on: [notify]
    code: |
      const ts = process.env.STEP_OUTPUT_NOTIFY_MESSAGE_TS;
      // 把 ts 存到你自己的数据库,方便后续更新那条消息 ...

Puntos clave:

  • module: dingyue-module-slack-deliver Es la identificación del módulo y la plataforma lo resolverá según el nombre + la versión.
  • inputs: Corresponde uno a uno con las entradas en el contrato del módulo.
  • Una vez completada la llamada, puede pasar {{steps.deliver.outputs.message_id}} Leer la salida del módulo.

Convierta los flujos de trabajo existentes en módulos: Promocionar a módulo

La mayoría de las veces no escribirás un módulo desde cero, sino que lo extraerás de un flujo de trabajo existente. Proceso:

  1. Abra un flujo de trabajo en el que crea que "vale la pena reutilizar esta lógica".
  2. Utilice la selección del marco del mouse o Mayús+clic para seleccionar varios pasos consecutivos en el lienzo.
  3. Menú contextual → "Ascender a módulo", o el botón con el mismo nombre en la barra de herramientas superior.
  4. En la ventana emergente:
    • Proporcione un nombre de módulo significativo (único a nivel mundial, se recomienda anteponerle el nombre de su equipo, por ejemplo: my-team-slack-notifier);
    • La plataforma inferirá automáticamente el primer borrador de entradas/salidas en función del fragmento seleccionado, que podrás editar;
    • Después de la confirmación, haga clic en "Crear módulo".
  5. These steps in the original workflow will be replaced with a sub_workflow node - parameters and connections are automatically aligned.
Modelo mental de Promover

Como la refactorización de "función de extracción" en el IDE. Seleccionas un fragmento de código y el IDE te ayudará a extraer una función con parámetros y valores de retorno, y reemplazará la posición original con la llamada. Braidrun hace exactamente lo mismo, pero para los pasos del flujo de trabajo.

Actualización del módulo y compatibilidad de versiones.

Cada vez que guarda un módulo, se crea una nueva versión. El flujo de trabajo principal se puede seleccionar en el paso sub_workflow:

  • version: latest — Utilice automáticamente la última versión (adecuada para módulos que usted mismo mantiene)
  • version: "1.2.0" — Bloqueado a una versión específica (adecuada para hacer referencia a módulos de otras personas, miedo a actualizar y dañar la compatibilidad)
  • version: "^1.2.0" — Permitir actualizaciones de versiones menores, prohibir versiones principales entre versiones

¿Qué es un "cambio compatible"?

  • ✓ Agregue una entrada opcional (los valores obligatorios/predeterminados no se consideran rotos)
  • ✓ Agregar un campo de salida
  • ✗ Eliminar/cambiar el nombre de la entrada
  • ✗ Eliminar/cambiar el nombre de la salida
  • ✗ Cambiar tipo de entrada

Al realizar cambios que rompan la compatibilidad, la versión semántica debe actualizarse a la siguiente MAYOR. La plataforma no aplica, pero está protegida cuando la persona que llama bloquea ^X.Y.Z.

Detección de bucle

El módulo A no puede hacer referencia indirecta a sí mismo. La plataforma realiza la detección en dos niveles:

  1. Detección estática en el momento de la liberación. — Al guardar un módulo, DFS escanea los gráficos de dependencia de todos los demás módulos a los que hace referencia y se niega a guardar si hay bucles.
  2. Detección dinámica en tiempo de ejecución — Si un ciclo resuelto por el tiempo de ejecución ocurre durante la ejecución (por ejemplo, se hace referencia a él después de una rama condicional), se generará un error inmediatamente.

La profundidad de recursividad máxima predeterminada es de 8 niveles. Esta es la profundidad del "hijo del padre del hijo", ni una sola llamada al fanout.

Aislamiento de variables

El módulo se ejecuta como un "WorkflowExecutionContext secundario", completamente aislado del contexto principal:

  • Las variables/salidas de pasos/agentes del padre no se heredan al hijo de forma predeterminada;
  • La salida del paso interno del niño no se desbordará al padre; el padre solo puede ver las salidas declaradas en el contrato;
  • La única forma de pasar datos entre padres e hijos es mediante entradas/salidas (contrato explícito).

Este aislamiento es la piedra angular de la confiabilidad modular: la "caja negra" no es una metáfora, es literal.

Degradar del módulo: restaurar el módulo a un paso en línea

Si lo modifica y descubre que cierta parte de la lógica en realidad se usa en un solo lugar y convertirla en un módulo aumenta el costo de comprensión, puede revertir la degradación:

  1. Seleccione el nodo sub_workflow en el flujo de trabajo principal;
  2. Haga clic derecho → "Degradar en línea";
  3. La plataforma expande el paso del módulo hacia atrás al flujo de trabajo principal y el nodo sub_workflow desaparece.

El módulo original en sí no se elimina; si hay otros flujos de trabajo que hacen referencia a él, siguen siendo válidos.

Dónde gestionar todos los módulos

La navegación principal "Biblioteca de módulos" a la izquierda es su vista general. Aquí puedes:

  • Vea una lista de todos los módulos (12 incluidos + los creados por su equipo)
  • Consulta inversa basada en "Quién hace referencia a mí": verifique quién se verá afectado antes de cambiar el módulo
  • Ver el historial de versiones del módulo/diff
  • Publicar/Archivar/Transferir propiedad

Cuando hacer módulos

  • ✓ La misma lógica aparece en más de 2 flujos de trabajo
  • ✓ Un contrato externo lógicamente estable y claro (normalmente "enviar mensajes/comprobar informes/generar Markdown")
  • ✓ Un único flujo de trabajo ha superado los 15 pasos y su legibilidad ha disminuido.
  • ✗ Una parte de la lógica solo se usa una vez y no se reutilizará en el futuro: directamente incorporada
  • ✗ Una pequeña función de utilidad de 2 a 3 líneas: la reutilización de código mediante pasos de código es más natural que los módulos

Siguiente paso