7

我有以下 Makefile:

#runs the working directory unit tests
test:
    @NODE_ENV=test; \
        mocha --ignore-leaks $(shell find ./test -name \*test.js);

#deploys working directory
deploy:
    @make test; \
    make deploy-git; \
    make deploy-servers;

#deploys working to git deployment branch
deploy-git:
    @status=$$(git status --porcelain); \
    if test "x$${status}" = x; then \
        git branch -f deployment; \
        git push origin deployment; \
        echo "Done deploying to git deployment branch."; \
    else \
        git status; \
        echo "Error: cannot deploy. Working directory is dirty."; \
    fi

deploy-servers:
#   for each server
#       @DEPLOY_SERVER_IP = "127.0.0.1"; \
#       make deploy-server

#deploy-server:
#   connect to this server with ssh
#   check if app is already running
#   stop the app on the server if already running
#   set working directory to app folder
#   update deployment git branch
#   use git to move head to deployment branch
#   start app again

请注意,deploy-servers并且deploy-server现在只是假人。这是deploy命令应该做的:

  1. 运行测试(make test),失败退出
  2. 将当前头推送到部署分支(make deploy-git),失败退出
  3. 拉取服务器上的部署分支 ( make deploy-servers)

您可以在 Makefile 中将其视为:

deploy:
    @make test; \
    make deploy-git; \
    make deploy-servers;

问题是我不确定如何防止make deploy-gitmake test失败时执行,以及如何防止make deploy-servers在测试失败或make deploy-git失败时执行。

有没有明确的方法可以做到这一点,或者我应该求助于使用 shell 文件或用普通的编程语言编写这些工具?

4

4 回答 4

14

shell 命令列表的退出状态是列表中最后一个命令的退出状态。只需将您的命令列表转换为单独的简单命令即可。默认情况下,make当命令返回非零时停止。所以你得到你想要的

deploy:
    @make test
    make deploy-git
    make deploy-servers

如果你忽略一个简单命令的退出状态,你可以在它前面加上一个破折号:

 target:
     cmd1
     -cmd2 # It is okay if this fails
     cmd3

您的make手册包含所有详细信息。

于 2012-05-11T22:03:21.267 回答
5

其他人给出的答案是基于将“配方”分成单独的命令。

在不可行的情况下,您可以做的是set -e在 shell 脚本中使其在命令失败时终止:

target:
        set -e ; \
          command1 ; \
          command2 ; command3 ; \
          ... commandN

这与set -e您将放置在 shell 脚本顶部附近以使其在某些命令未成功终止时保释的方式相同。

假设我们对 和 的终止状态不command2感兴趣command3。假设这些指示失败或不可靠地使用终止状态是可以的。然后,set -e我们可以编写显式退出测试,而不是编写代码:

target:
        command1 ; \
        command2 || exit 1 ; \
        command3 ; \
        true  # exit 0 will do here also.

由于command3可以指示失败,并且我们不希望它使我们的构建失败,因此我们添加了一个成功的虚拟命令。

于 2012-05-12T01:01:53.530 回答
2

make应该已经这样做了;它使用 执行复杂sh -e的命令,如果命令非零退出(只要它不在与 POSIX 兼容的 shell 中的循环中),它将中止执行,并在Makefile命令失败时中止整个命令,除非您明确告诉它不要这样做。如果您感到偏执,可以在命令中使用&&代替。;

于 2012-05-11T21:49:24.080 回答
0

我通过在潜在断点处代理到新的 make 命令解决了这个问题:

.PHONY cmd_name cmd_name_contd

cmd_name:
    if [ "`pwd`" = "/this/dir" ]; then make cmd_name_contd; fi

cmd_name_contd:
    @echo "The directory was good, continuing"

这样,如果目录错误,它只是静默退出,您还可以添加带有消息的 else 条件以在失败时显示。

于 2014-10-24T07:05:42.883 回答