在撰寫一些自動化流程的時候覺得 Makefile 的寫法不習慣,或是環境的支援太薄弱嘛?覺得 Makefile 的寫法太過古老,每次撰寫都像是在寫古文嘛?給 Taskfile 一個機會吧

有別於 Makefile 的地方

基本上 Taskfile 跟 Makefile 都是為了一些自動化流程需求所發展出來的工具,既然目的相同又謂何要換呢?

Windows 上的安裝

若是有 Chocolatey 或是 Scoop 的話有很方便的安裝指令

1
choco install go-task
1
scoop install main/task

當然 winget 也是可以

1
winget install Task.Task

若上述的工具都沒有,官網有詳細介紹各種安裝方式。

使用不同版本 (Taskfile versions)

標示 Taskfile 所使用的版本可以使用特定版本才開放的功能。可以從這邊確認一下新的版本有提供什麼不同的功能。

變數 (Variables)

在介紹變數前先參考這份簡易的範例。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
version: '3'
env: # global scope
  YOUR_NAMESPACE: your-namespace

vars: # global scope
  MY_NAMESPACE: my-namespace
  HELM_VERSION: v3.5.0
  K8S_NAME: cluster-name
  VERSION: latest

tasks:
  install:helm:
    desc: install helm from sources
    cmds:
      - wget -qO- https://get.helm.sh/helm-{{.HELM_VERSION}}-{{OS}}-{{ARCH}}.tar.gz | tar xvz -C ./
  
  default:
    desc: default task
    cmds:
      - echo ${YOUR_NAMESPACE} {{.MY_NAMESPACE}}

  # local scope (in task scope)
  demo:dynamic-var-task:
    desc: 'A sample for dynamic variable, using curl and jq to generate content.'
    cmds:
      - echo '{{.CURRENT_TIME}}'
      - echo '----------------------------------------------------------------------------'
      - echo "${CT}"
    vars:
      CURRENT_TIME:
        sh: "curl 'https://api.github.com/repos/jqlang/jq/commits?per_page=5' | jq '.[0]'"
    env:
      CT:
        sh: "curl 'https://api.github.com/repos/jqlang/jq/commits?per_page=5' | jq '.[1]'"
  
  # local scope (with default value)
  demo:vars-task:
    desc: 'A sample to show how internal task use.'
    # must use key word `default` to let outside change the value
    vars:
      QQ: '{{default "default value" .QQ}}'
    cmds:
      - cmd: echo "{{.Result}}"
        vars:
          Result: 
            sh: pwd
      - cmd: echo "Print local vars {{.QQ}}"

Taskfile 可以接受的變數類型有以下幾種:

  • .env 檔案

    Taskfile 可以接受 .env 檔案,並將裡面的 Key/Value pair 識別為全域變數 (global variable)。 在 Taskfile 內可以使用 ${Your_Variable_Name_In_File} 存取。

  • 全域變數

    可以在 Task file 內最外層宣告 env 來存放全域變數。在 Taskfile 內可以使用 ${Your_Variable_Name_In_File} 存取。

    另外一種是宣告 vars 來存放全域變數,不過在 Taskfile 內需要使用 {{.Your_Variable_Name_In_File}} 來存取變數。

    PS 若 {{}} 內沒有 . 在前面的變數那些就是內建的變數,請參考這裡

  • task 內變數

    在 tasks 區塊內的變數跟全域相比就是無法跨越 task 分享變數的內容,而存取的方式跟一樣跟如何宣告有關。

    若用 env 存放變數則用,${Your_Variable_Name_In_File} 來取用變數,若是 vars 存放變數則用 {{.Your_Variable_Name_In_File}} 來取用。

  • CLI 傳入變數

    宣告在 tasks 區塊內的變數也可以從呼叫端傳入,可以是 task 互相呼叫時傳入的動態值,也可以是下 CLI 時傳入。

    但要特別注意的是,需要有 default 保留字,他才會吃傳入的變數,不然就只是固定的值

    1
    
    task demo:vars-task QQ='Hello World~'
    

相依任務 (Task dependencies)

很多時候一個任務會需要由多個小任務來組成,一來是這樣寫單一任務比較單純好維護,二來是這樣做可以讓任務有機會可以被其他任務複用。

一個簡單的例子:

1
2
3
tasks:
  foo:
    deps: [foo, bar]

上面這個 task 顯示執行這個 task 的 cmds 之前,他會需要先執行完 foobar 這兩個 task。還有另外一種方式可以作到類似的事情。可以參考以下的寫法:

1
2
3
4
5
tasks:
  foo:
    commands:
      task: foo
      task: bar

Sample

這邊放上我個人練習用的 script

Reference