4 个稳定版本

1.1.2 2021 年 12 月 11 日
1.0.0 2021 年 12 月 5 日

#1237 in 开发工具

MIT 许可证

90KB
1.5K SLoC

nauman

Crates.io License CI

本地作业自动化的 CI 启发式方法。

特性安装使用方法常见问题示例作业语法

关于

nauman 是一款易于使用的作业自动化工具。它源于在保持监控和调试能力的同时自动化复杂任务流程的需求。

它深受 Github Actions 的简洁性、Fastlane 的灵活性以及 Apache Airflow 的扩展性启发。此工具旨在将两者中的最佳之处带给本地作业自动化。

快速开始

请参阅 安装 了解如何在您的计算机上安装。尝试运行 nauman --version 以确保它已正确安装。

一旦 nauman 安装并运行,请创建一个名为 hello-world.yml 的作业文件,位于项目根目录,内容如下

name: Hello World!

tasks:
  - name: Hello World!
    run: echo "Hello World!"
  - name: Greeting
    run: echo "Greetings ${USER}!"

当你调用 nauman hello-world.yml 时,它将按照文件中列出的顺序运行作业任务。输出应如下所示

--------------------------
--- Task: Hello World! ---
--------------------------
$ echo "Hello World!"
Hello World!
----------------------
--- Task: Greeting ---
----------------------
$ echo "Greetings ${USER}!"
Greetings egordm!

nauman 将每个任务的输出打印到控制台。定义的任务将在您的默认 shell 中运行并捕获它们的所有输出。

(返回顶部)

示例

有关更多示例,请参阅 示例 目录。

使用 Hooks

钩子nauman中的第一类公民。它们代表在作业执行过程中可能发生的事件和回调。

让我们看看钩子的一个简单用例,用于向作业及其任务添加健康检查。在项目的根目录下创建一个名为health-checks.yml的文件,并包含以下内容

name: Example Job Using Health Checks
policy: always

tasks:
  - name: Run a successful program
    run: sleep 2 && echo "Success!"
    hooks:
      on_success:
        - run: curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/fb4c4863-a7f1-44f1-8298-3baabec653d4
  - name: Run a failing program
    run: sleep 2 && exit 1
    hooks:
      on_success:
        - run: curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/0178d446-9b50-4158-b50d-7df098945c81
      on_failure:
        - name: Send failing status code to Health Check
          run: curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/0178d446-9b50-4158-b50d-7df098945c81/$NAUMAN_PREV_CODE

hooks:
  after_job:
    - name: On completion of the job, ping a health check
      run: curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/fb4c4863-a7f1-44f1-8298-3baabec653d4

当你调用nauman health-checks.yml时,它会运行作业文件中的所有任务,尽管第二个任务失败了(参见执行策略:始终)。以下是输出

--------------------------------------
--- Task: Run a successful program ---
--------------------------------------
$ sleep 2 && echo "Success!"
Success!
-------------------------------------------------------------------------------------------------------------
--- Hook: curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/fb4c4863-a7f1-44f1-8298-3baabec653d4 ---
-------------------------------------------------------------------------------------------------------------
$ curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/fb4c4863-a7f1-44f1-8298-3baabec653d4
-----------------------------------
--- Task: Run a failing program ---
-----------------------------------
$ sleep 2 && exit 1
Task "Run a failing program" completed in 2s with a non-zero exit status: 1. This indicates a failure
------------------------------------------------------
--- Hook: Send failing status code to Health Check ---
------------------------------------------------------
$ curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/0178d446-9b50-4158-b50d-7df098945c81/$NAUMAN_PREV_CODE
-----------------------------------------------------------
--- Hook: On completion of the job, ping a health check ---
-----------------------------------------------------------
$ curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/fb4c4863-a7f1-44f1-8298-3baabec653d4

第一个任务成功时,会执行成功钩子,发送健康检查。第二个任务失败时,会执行失败钩子,发送失败的健康检查。最后,执行作业后钩子,发送作业完成健康检查。

(返回顶部)

日志记录

日志记录nauman的一个强大功能,允许您将任务和钩子的输出记录到不同的输出流。

在项目的根目录下创建一个名为logging.yml的文件,并包含以下内容

name: Example Job Using Logs
options:
  log_dir: ./logs

tasks:
  - name: Print Hello World to stdout
    run: echo "Hello World!"
  - name: Print Hello World to stderr
    run: echo "Hello World!" >&2

logging:
  - type: file
    name: Print stdout to a file
    stdout: true
    stderr: false
    output: ./stdout.log
  - type: file
    name: Print stderr to a file
    stdout: false
    stderr: true
    output: ./stderr.log
  - type: file
    name: Print both stdout and stderr to separate files per task
    split: true
    output: ./separate_logs
  - type: console

运行nauman logging.yml,然后查看以下输出

-----------------------------------------
--- Task: Print Hello World to stdout ---
-----------------------------------------
$ echo "Hello World!"
Hello World!
-----------------------------------------
--- Task: Print Hello World to stderr ---
-----------------------------------------
$ echo "Hello World!" >&2
Hello World!

此外,还创建了以下文件

  • logs/logging_2021-12-05T18:11:14/
    • separate_logs/
      • 000_print-hello-world-to-stdout.log
      • 001_print-hello-world-to-stderr.log
    • stderr.log
    • stdout.log

日志位于指定的日志根目录(参见日志记录中的log_dir以获取更多详细信息)。所有日志都放置在一个logging_子目录中,该子目录包含作业运行的当前日期和时间。为每个日志流创建了stdout.logstderr.log。为每个任务创建了一个separate_logs/,其中包含该任务的stdout和stderr日志。

(返回顶部)

使用环境变量

环境变量允许您为作业设置环境变量。有多种方法可以设置环境变量

  • 作为系统环境变量:KEY=VALUE nauman
  • 作为cli参数:nauman -e KEY=VALUE
  • 作为作业配置:<job_file>.env.KEY: VALUE
  • 作为任务配置:<job_file>.tasks.<task>.env.KEY: VALUE

通过在项目根目录下创建一个名为env-vars.yml的文件,并包含以下内容,您可以测试所有这些

name: Example Environment variables

env:
  PING_CMD: curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/
  CHECK_1: fb4c4863-a7f1-44f1-8298-3baabec653d4

tasks:
  - name: Job env var
    run: echo $PING_CMD$CHECK_1
  - name: Task env var
    run: echo $PING_CMD$CHECK_1
    env:
      CHECK_1: fb4c4863-a7f1-44f1-8298-3baabec653d4
  - name: System env var
    run: echo $PING_CMD$CHECK_2
  - name: Built-in env vars
    run: echo "Previous task \"$NAUMAN_PREV_NAME\" finished with status $NAUMAN_PREV_CODE"

当您运行nauman env-vars.yml -e CHECK_2=0178d446-9b50-4158-b50d-7df098945c81时,您将看到以下输出

-------------------------
--- Task: Job env var ---
-------------------------
$ echo $PING_CMD$CHECK_1
curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/fb4c4863-a7f1-44f1-8298-3baabec653d4
--------------------------
--- Task: Task env var ---
--------------------------
$ echo $PING_CMD$CHECK_1
curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/fb4c4863-a7f1-44f1-8298-3baabec653d4
----------------------------
--- Task: System env var ---
----------------------------
$ echo $PING_CMD$CHECK_2
curl -fsS -m 10 --retry 5 -o /dev/null https://hc-ping.com/0178d446-9b50-4158-b50d-7df098945c81
-------------------------------
--- Task: Built-in env vars ---
-------------------------------
$ echo "Previous task \"$NAUMAN_PREV_NAME\" finished with status $NAUMAN_PREV_CODE"
Previous task "System env var" finished with status 0

在上一项任务中,我们可以看到使用了 NAUMAN_PREV_NAMENAUMAN_PREV_CODE 环境变量。这些变量由 nauman 根据 previous task 设置。有关特定环境变量的更多上下文,请参阅 环境变量

(返回顶部)

功能

挂钩一切

您可以为作业或任务的所有可能结果和事件创建挂钩。创建如下作业或任务局部挂钩

tasks:
  ...
  - name: My Task
    hooks:
      on_failure:
        ...
      on_success:
        ...
      before_task:
        ...
      after_task:
        ...

hooks:
  before_job:
    ...
  after_job:
    ...
  on_failure:
    ...
  on_success:
    ...
  before_task:
    ...
  after_task:
    ...

(返回顶部)

灵活的日志记录

您可以记录到单个或多个文件,控制台,甚至选择要使用的日志流(stdout、stderr 或两者都使用)。

logging:
  - name: Log only stdout
    type: file
    stdout: true
    stderr: false
    output: ./stdout.log
  - name: Logs split in files per task
    type: file
    stdout: true
    stderr: true
    split: true
    output: ./per_task_logs
  - name: Logs to console
    type: console
    stdout: true
    stderr: true
  - name: Append output to a shared file
    type: file
    stdout: true
    stderr: true
    output: /var/log/nauman/my_job.log

(返回顶部)

上下文变量

使用上下文变量定义更灵活的任务。

目前支持以下上下文变量

  • NAUMAN_JOB_NAME - 作业名称
  • NAUMAN_JOB_ID - 作业 ID
  • NAUMAN_TASK_NAME - 当前任务名称
  • NAUMAN_TASK_ID - 当前任务 ID
  • NAUMAN_PREV_NAME - 上一任务名称
  • NAUMAN_PREV_ID - 上一任务 ID
  • NAUMAN_PREV_CODE - 上一任务的退出代码
tasks:
  ...
  - name: Use context vars as env vars
    run: echo $NAUMAN_TASK_NAME

(返回顶部)

可配置的任务计划

当一个任务失败时,不会停止整个作业。您可以配置任务执行计划以决定如何继续。

您可以选择以下选项之一

  • always - 不论先前任务状态如何,总是执行任务。
  • prior_success - 只有在先前任务成功时才执行任务。
  • no_prior_failed - 只有在没有其他任务失败时才执行任务。
# Policy can be defined at job level
policy: no_prior_failed

tasks:
  ...
  - name: Always run this task
    # And overridden at task level
    policy: always

(返回顶部)

不同的 shell 类型

除了默认的 sh shell 之外,您还可以使用 bashpythonrubyphp 或指定您自己的 shell 路径。

# Specify a default shell
shell: bash
shell_path: /bin/bash

tasks:
  ...
  - name: Python task
    shell: python
    run: print('Hello World!')
  - name: Virtual env python
    shell: python
    shell_path: '/app/venv/bin/python'
    run: print('Hello World!')
  - name: Ruby task
    shell: ruby
    run: print('Hello World!')
  - name: PHP task
    shell: php
    run: echo 'Hello World!';

(返回顶部)

干运行

想确保作业配置正确?您可以在干运行模式下运行作业。这将验证所有任务在语法上是否正确,所有 shell 是否可用,并警告您关于任何潜在问题(如缺失目录)。

nauman --dry-run my_job.yml

(返回顶部)

任务输出

在执行每个任务期间,都会创建一个临时文件,您可以在其中存储输出变量。这些文件在任务完成后会自动删除。输出文件中指定的变量将作为环境变量加载到全局上下文中。

输出文件接受 dotenv 风格的语法。

tasks:
  ...
  - name: Append output to the output file
    run: echo "foo=bar"  >> "$NAUMAN_OUTPUT_FILE"
  - name: Use the output variable
    run: echo $foo

(返回顶部)

多行命令

有时命令可能比单行占用的空间更多。您可以使用多行字符串来定义您的命令。

tasks:
  ...
  - name: Multiline
    shell: python
    run: |
      import os
      print(os.environ['NAUMAN_TASK_NAME'])

(返回顶部)

dotenv 文件

您可以使用 dotenv 文件为您的任务定义变量。

options:
  dotenv: /path/to/my_env.env

(返回顶部)

更改工作目录

您可以使用 cwd 选项更改工作目录。

cwd: /my/project/dir

tasks:
  ...
  - name: Change working directory to /my/project/dir/task1
    cwd: ./task1
    run: pwd

(返回顶部)

常见问题解答

为什么使用 nauman?

想象一下:您想定期运行同步您喜欢的电影在不同服务之间的工具。这可以通过 cron 作业完成,但如果您想添加更多依赖任务(例如,同步您的电影收藏),怎么办?很简单,创建一个运行它们的 shell 脚本。

现在,您想跟踪它们的输出(用于调试),您想添加健康检查、单进程锁定等。Shell 脚本并不是做这件事的最佳方式,而且很容易变得非常混乱。

使用 nauman,您可以创建并运行一个作业文件,以可读和可维护的方式涵盖所有内容。

此外,nauman 是用 Rust 编写的,可以作为简单的二进制文件无膨胀地安装在任何系统上。(有关详细信息,请参阅 安装)。

何时不使用nauman?

以下情况下不应使用nauman

  • 需要makefile的任务
    • nauman不是makefile的替代品。
    • 它旨在运行一个任务来自动化一个单独的任务链。
    • 它不支持任务并行处理、递归或其他复杂的工作流程。
  • 数据自动化工具
    • nauman不是数据自动化工具的替代品。
    • 它可以用来将多个数据处理任务串联起来。
    • 但它不提供数据加载、数据处理或可视化的任何功能。
  • CI工具
    • nauman不是CI工具的替代品。
    • 它不包含任何CI特定的功能,如缓存、构建上传或与构建工具的集成。

(返回顶部)

安装

nauman的二进制文件名为nauman

Windows、macOS和Linux的预编译二进制文件存档可用于nauman。Linux和Windows的二进制文件是静态可执行文件。未明确提及平台的使用者建议下载这些存档之一。

如果你是Rust程序员,可以使用cargo安装nauman。

  • 请注意,numane与Rust 1.57.0进行了测试,尽管nauman可能与较旧版本兼容。
  • 请注意,二进制文件可能比预期的大,因为它包含调试符号。这是故意的。要删除调试符号并因此减小文件大小,请在二进制文件上运行strip。
$ cargo install nauman

从源代码构建

nauman是用Rust编写的,因此你需要获取一个Rust安装才能编译它。nauman使用Rust 1.57.0(稳定版)或更高版本编译。通常,nauman跟踪Rust编译器的最新稳定版。

要构建nauman

$ git clone https://github.com/EgorDm/nauman
$ cd nauman
$ cargo build --release
$ ./target/release/nauman --version

(返回顶部)

用法

调用nauman的通常方法是用nauman <job_file>命令。如果你想指定更多选项或覆盖某些作业设置,请参阅下面的完整用法

USAGE:
    nauman [OPTIONS] <JOB>

ARGS:
    <JOB>    Path to job yaml file

OPTIONS:
        --ansi <ANSI>                Include ansi colors in output (default: true)
        --dry-run <DRY_RUN>          Dry run to check job configuration (default: false)
    -e <ENV>                         List of env variable overrides
    -h, --help                       Print help information
    -l, --level <LEVEL>              A level of verbosity, and can be used multiple times (default:
                                     info) [possible values: debug, info, warn, error]
        --log-dir <LOG_DIR>          Directory to store logs in (default: current directory)
        --system-env <SYSTEM_ENV>    Whether to use system environment variables (default: true)
    -V, --version                    Print version information

(返回顶部)

作业语法

替代方案

如果这不是你想要的,请查看这些酷炫的替代方案

  • Bash或Makefile
  • just - 是一种方便的方式来保存和运行项目特定的命令
  • fastlane - 是iOS和Android开发人员用于自动化诸如生成截图、处理配置文件和发布应用程序等繁琐任务的工具
  • Apache Airflow - 是由社区创建的一个平台,用于以编程方式创建、安排和监控工作流程。

(返回顶部)

待办事项

  • 添加对.env文件的支持
  • 添加更多测试
  • 添加一种原生前端运行Web请求的方法
  • 添加一种将不同任务输出写入的方法
  • 添加一种模板化系统
  • 添加一种指定是否启用或禁用每个日志的ANSI的方法
  • 添加flock支持
  • 始终添加控制台日志(仅指定是否应记录stdout和stderr)

贡献

由于这是一个爱好项目,因此非常欢迎贡献!

目前,你最容易的贡献方式是使用nauman,看看它在哪些方面有所欠缺。

如果你有nauman未涵盖的使用案例,请提交一个问题。这对我很重要,对希望为项目做出贡献的任何人来说也很重要,如果你实现了该功能,对你来说也很重要。

如果您有兴趣帮助修复现有问题,或者您刚刚提交的问题,您的帮助将受到欢迎。

有关贡献的技术信息,请参阅CONTRIBUTING

(返回顶部)

许可证

本项目遵循MIT许可证条款。请参阅LICENSE文件。

(返回顶部)

依赖项

~11-23MB
~279K SLoC