功能列表
Walis 目前具備的所有功能,依你會去找的位置分組。每一條都是現行版本已經有的東西,不是路線圖。
任務與腳本
| 功能 | 說明 |
|---|---|
| 兩種撰寫模式 | 腳本模式直接編輯 shell;流程模式用動作組出腳本。 |
| 33 個內建動作 | 八個分類:通用、檔案、Git、Node、.NET、容器、部署、檢查。見動作。 |
| 自訂動作 | 參數宣告加上 shell 樣板,以 JSON 儲存,不必寫程式。 |
| 編譯而非解譯 | 流程在儲存時編譯進 Jobs.Command,所以執行器完全不需要知道動作的存在。 |
| AI 檢查腳本 | 把腳本送給設定好的供應商,回報看起來有問題的地方。 |
| 匯出與匯入 | 任務與自訂動作以 JSON 進出,依名稱比對,可選擇覆寫。識別碼與建置紀錄保留。 |
| 從 Jenkins 匯入 | 貼上 Jenkinsfile(宣告式或腳本式)或任務的 config.xml,Walis 轉成帶警告清單的草稿並在編輯器開啟。按下儲存之前什麼都不寫。見對應表。 |
| 建置參數 | 每個任務最多 50 個:string、text、choice、boolean、password。手動執行會先問,排程用預設值。不認識的名稱是拒絕,不是忽略。 |
| 伺服器端清單 | 分頁、排序、搜尋與篩選都在 SQL 裡做,所以三十個任務和三千個任務的清單表現一樣。 |
從流程模式切到腳本模式會保留編譯結果;反向切回去會還原步驟,腳本模式下的手動修改不保留。
建置與步驟
| 功能 | 說明 |
|---|---|
| 逐步驟狀態 | 每個步驟各自有狀態、輸出、結束碼與耗時。 |
| 獨立的 shell | 步驟共用工作目錄,但不共用環境變數。要傳值就往 $WALIS_ENV_FILE 追加 KEY=VALUE。 |
| 步驟依賴 | 流程是一張有向無環圖:步驟宣告自己依賴誰,沒在等別人的就同時跑——每個建置最多 8 步。有清單與圖兩種檢視。 |
| 步驟輸出 | 步驟往 $WALIS_OUTPUT_FILE 寫 name=value,後面的步驟用 ${{ steps.識別字.名稱 }} 引用。值以環境變數注入,不會被拼進腳本文字。會存進建置紀錄,日誌看得到。 |
| 依資料決定跑不跑 | 用一段運算式對前面步驟的輸出與環境求值,決定這一步跑不跑。同一個上游接出兩條互斥條件的分支就是 if/else。 |
| 執行條件 | 每個步驟可設「前面都成功才執行」(預設)、「總是執行」或「只在前面失敗時執行」——就是 Jenkins 的 post {}。失敗不再中止建置:收尾與通知步驟照跑,一般步驟標成 Skipped,結果仍算失敗。 |
| 逐步驟重試 | 第一次之外再試 0–10 次,每次都是全新的 shell,前幾次的輸出留在上面。重試用的是任務逾時,不會延長它。 |
| 同一時間只跑一筆 | Jenkins 的 disableConcurrentBuilds()。關卡跟「Queued → Running」在同一個交易裡,兩個節點搶不可能都贏;搶輸的會重新排回佇列而不是把建置弄丟。 |
| 下游任務 | 每個任務最多 20 個對象,可選成功時/失敗時/總是,以名稱比對。下游拿得到 WALIS_UPSTREAM_JOB、_BUILD 與 _STATUS。鏈長到十層就停,觸發時用上游任務的執行角色檢查權限。 |
| 建置矩陣 | {"NODE":["20","22"],"OS":["mac"]} 展開成多筆建置,上限 50 組。 |
| 建置快取 | 指定路徑在成功後保存,下次建置還原——在清空工作目錄之後,不是之前。 |
| 產出檔案 | 成功後複製出來,上限 200 檔/64 MB,可在日誌視窗下載。 |
| 即時輸出 | stdout 與 stderr 依實際順序交錯;日誌視窗每兩秒重取並自動捲到底,往上捲就停止跟隨。 |
| 逾時 | 整場建置的總時限,每個步驟拿到的是剩餘時間。 |
| 保留期限 | 建置紀錄、產出檔案與稽核紀錄共用同一個保留天數。 |
動作設定 continueOnError 時,建置根本不會被標成失敗,後面照常進行。
觸發方式
- 手動——任務清單與詳情頁上的按鈕。
- 推送——
POST /api/webhooks/push接受 GitHub、GitLab 與{repository, branch}三種格式,依分支與正規化後的儲存庫位址比對任務。設定密鑰後需帶X-Hub-Signature-256、X-Gitlab-Token或X-Walis-Token。 - 排程——五欄位 Cron,每分鐘依設定的時區比對一次。
三者互斥——一個任務只有一種觸發方式。用手執行是另一回事、永遠都可以,所以「手動」的意思是「沒有自動觸發」,不是「只能這樣啟動」。
執行器
| 功能 | 說明 |
|---|---|
| 內建本機執行器 | 跑在 API 程序內,併發數來自系統設定。 |
| 遠端代理 | walis-runner 輪詢、認領、回報。目標機器不必安裝任何執行環境——它是自帶執行檔。 |
| 共用步驟迴圈 | BuildStepSequence 本機與遠端是同一份程式,差別只在寫資料庫還是送 HTTP。 |
| 標籤與插槽 | 自由標籤,加上每台執行器的插槽數。 |
| 心跳 | 每分鐘回報;超過五分鐘沒消息就標記離線,可觸發通知。 |
資料庫與高可用
| 資料庫 | 多節點 | 說明 |
|---|---|---|
| SQLite | 不行 | 預設值。單一檔案,不必另外跑東西。 |
| PostgreSQL | 可以 | |
| MySQL / MariaDB | 可以 | |
| SQL Server | 可以 | 含 Azure SQL。 |
多個 API 節點指向同一個資料庫伺服器,就會分工:
- 原子認領建置——兩個節點可以搶同一筆佇列中的建置,但只有一個能完成
Queued→Running。 - 租約選主——Cron 觸發、離線偵測、保留期限清理與排程備份同一時間只在一個節點上跑。 租約會過期,持有者掛掉不需要額外的協調服務就會換人。
- 跨節點輪詢——某個節點排入的建置,由當下有餘裕的節點接手。
- 逐節點回收——節點重啟時只回收自己中斷的建置。
GET /health 會回報資料庫種類、節點名稱,以及是否為多節點部署。從 SQLite 搬家就是一次備份 加一次還原,因為備份檔與資料庫種類無關。見高可用。
建置隔離與安全
建置跟服務以同一個身分執行,所以真正在防的是這幾件事。
所有平台:
- 允許的工作目錄——清單非空時,工作目錄不在其中的建置直接失敗,而不是跑到意料之外的地方。
- 環境白名單——建置不繼承服務的環境,只拿得到
PATH、USER、LOGNAME、SHELL、語系、 暫存目錄與 TLS 憑證那幾個變數,其餘一概沒有,連線字串與服務機密根本不在裡面。POSIX 上名稱 區分大小寫比對,因為把Path當成PATH會讓大小寫不同的機密溜過去。 - 清空工作目錄——只刪目錄內容,且拒絕磁碟根目錄、家目錄與層級過淺的路徑。
macOS:
- 沙箱——
IsolateBuilds(預設開啟)時每個步驟以sandbox-exec包住,不能讀寫 Walis 資料目錄、 資料庫所在目錄、備份目的地與你列出的路徑。 - 符號連結解析——沙箱路徑逐段解析,所以
/tmp、/var/folders的規則真的會生效。
其他平台預設以未隔離方式執行。 Windows 與 Linux 上 Walis 沒有對應的機制,遠端執行器本身也不套用沙箱, 所以在那些地方,腳本擁有執行它的帳號的權限。這是預設值,為的是每個平台第一次建置就能執行。 建置日誌開頭會註明;內建執行器屬於這種情況時,設定頁會顯示警告。
管理員可以改成要求隔離邊界,也就是開啟系統設定 → 建置的「沒有隔離邊界時拒絕執行」。之後:
- Windows 或 Linux 上的內建執行器會拒絕執行建置:「系統要求隔離建置,但此執行器沒有可套用的沙箱」。
- 遠端執行器要由 Walis 之外的東西隔離(容器、VM)、自己這樣宣告,而且管理員把它的名字列進「已置於外部隔離的執行器」,才領得到工作。宣告
external但不在清單上的執行器會被拒絕—— 光憑請求標頭不算數。
這些都不是完整隔離——同一個使用者、同一台機器。它擋的是「建置腳本順手把資料庫或憑證讀走」。 要更強的邊界,就把建置放到用獨立帳號跑的執行器上,或讓腳本自己起容器。
存取控制
| 功能 | 說明 |
|---|---|
| 選用的登入 | 預設關閉。關閉時所有人視為管理員。 |
| 密碼保存 | PBKDF2-SHA256,工作階段存在資料表。 |
| 一次性密碼 | TOTP 加備援碼,可要求所有帳號啟用。 |
| 角色 | viewer、operator、administrator。 |
| 任務層級權限 | 每個任務各有檢視角色與執行角色。 |
| 安靜的 404 | 看不到的任務回 404 而不是 403——回應不會透露它存在。 |
| API 金鑰 | walis_<前綴>_<124 位元祕密>,資料庫只存 domain-separated SHA-256 lookup hash,明文只顯示一次。用途分成 mcp(安全預設,只能到 /mcp)、api 與 runner——runner 金鑰綁定單一執行器名稱,只能替它註冊、心跳、認領與回報。任何金鑰都不能碰登入、帳號與金鑰本身。 |
外掛
動作外掛在 Jint(純 C# 的 JavaScript 直譯器)中執行,回傳的是一段 shell 而不是行為——所以安裝前就能讀到它會跑什麼。
- 只有宣告過的能力——連外僅限指定網域;機密只能經
withSecret填進標頭,外掛讀不到值。 - 資源上限——逾時 10 秒、記憶體 8 MB、語句 50 萬、遞迴 64 層。
- AI 產生草稿——權限一律清空、類型與版本強制寫死、絕不自動安裝。
- 僅限管理員——安裝外掛等於加入一段會被執行的程式碼。
通知
電子郵件、Slack(Incoming Webhook)與自訂 JSON webhook,各自獨立開關與測試。五種事件:建置失敗、建置恢復、每次建置成功、建置逾時、執行器離線。靜音時段內只送失敗。派送紀錄會保存。
AI 協助
支援 Claude、Gemini 與 Codex。Claude 走官方 Anthropic SDK,另兩家走各自的 REST 端點。用於腳本檢查、失敗分析與外掛草稿。每次呼叫都記錄供應商、模型、用途、耗時、用量與結果——不保存提示詞內容。
備份與還原
- 依 Cron 排程,以有驗證的格式加密(PBKDF2-SHA256、AES-256-GCM 區塊)——被改過或被截斷的壓縮檔會在還原任何內容之前就被拒絕。
- 打包資料庫(
VACUUM INTO)、產出檔案、你列出的額外路徑,以及選用的 PostgreSQL(pg_dump)。 - 目的地:本機路徑、S3 相容(自簽 SigV4)、Dropbox、Google Drive、OneDrive,都不依賴外部執行檔。
- 還原與資料庫種類無關,可以還原到另一種資料庫。
有遠端目的地時通關密語為必填,因為備份內含密碼雜湊與各種憑證。
可觀測性
- 總覽——啟用中的任務、近 7 日成功率、執行中數量、失敗次數、建置趨勢、最近建置、執行器負載與各任務成功率。
- Prometheus——
GET /metrics,刻意放在/api之外讓本機的抓取端有個固定路徑, 但驗證中介層仍然要求管理員身分。內容是彙總數字加上任務名稱。 - 稽核紀錄——任務、建置、執行器、環境變數、設定、通知與翻譯,共用保留天數。
整合
- REST API 涵蓋介面做得到的所有事。
- MCP 由 API 自己在
/mcp提供,代理只要網址加金鑰,本機不必安裝任何東西。Source/Walis.Mcp是給只支援 stdio 的用戶端用的轉接程式。 - 設定可攜——任務與自訂動作以可 code review 的 JSON 匯出匯入。
多語
繁體中文是來源語言,英文與日文以字典隨附,載入時再疊上你設定的覆寫。翻譯可在介面內編輯、以 JSON 匯入匯出,並可對未完成項目做自動翻譯。
部署
deploy/release.sh 會產出 self-contained 執行檔——目標機器不必先裝 .NET——涵蓋 Windows(x64、arm64)、macOS(Intel、Apple Silicon)與 Linux(x64、arm64、樹莓派的 32 位元 arm,以及兩種架構的 musl/Alpine)。每個平台一個壓縮檔,內含把管理介面一起打包好的 API 與執行器,並附上 SHA256SUMS.txt。
在 macOS 上,deploy/install.sh 註冊兩個 LaunchDaemon:服務本體(以一般帳號而非 root 執行)與盯著觸發檔的 restarter。其他平台就用你原本在用的 init 系統把執行檔跑起來。內建的自我更新任務拉程式碼、建置、切換符號連結、touch 觸發檔——重啟發生在建置的程序樹之外,所以建置活得夠久,能把自己的結果寫回去。
API 會把 wwwroot 一起服務,所以管理介面與 API 同源、同一個 port。