Open2

気になったもの触ってみるメモ

nappanappa

werk

コマンドランナーはたまにjustを使っていたが、べつのものを見つけたので試してみようと思う

Repo

https://github.com/simonask/werk

Install

labo/20250126_werk on  master [?] on ☁️  (ap-northeast-1)git clone https://github.com/simonask/werk
Cloning into 'werk'...
remote: Enumerating objects: 1336, done.
remote: Counting objects: 100% (149/149), done.
remote: Compressing objects: 100% (62/62), done.
remote: Total 1336 (delta 94), reused 108 (delta 85), pack-reused 1187 (from 1)
Receiving objects: 100% (1336/1336), 534.20 KiB | 7.03 MiB/s, done.
Resolving deltas: 100% (849/849), done.

labo/20250126_werk on  master [?] on ☁️  (ap-northeast-1)cd werk/

werk on  main via 🦀 v1.84.0 on ☁️  (ap-northeast-1)cargo install --path werk-cli
  Installing werk-cli v0.1.0 (/Users/yamashitashuuhei/ghq/github.com/yamashitashuuhei/labo/20250126_werk/werk/werk-cli)

werk on  main via 🦀 v1.84.0 on ☁️  (ap-northeast-1)
❯ werk --version
werk-cli 0.1.0 (1d010afb 2025-01-26)

Hello World

こんな感じの Werkfile を書いてタスクを定義する

config default = "hello"

task hello {
    info "Hello, World!"
}

werk コマンドで実行

werk/tmp on  main [?] on ☁️  (ap-northeast-1) 
❯ werk
[info] Hello, World!
[ ok ] hello

こういう実行もできる

cargo run -p werk-cli -- -f Werkfile

Usage

task task-name {
    # 変数定義
    let my-program-target = "my-program"

    # Run tasks or build recipes before this task. May be a list or a single name.
    build "my-program"

    # Enable forwarding the output of executed commands to the console.
    capture false

    # Set an environment variable for all child processes in this recipe.
    env "MY_VAR" = "value"

    # Remove an environment variable for all child processes in this recipe.
    env-remove "MY_VAR"

    # Run an external program after building this task's dependencies.
    run "echo \"Hello!\""

    # Can also run a block of commands.
    run {
        "echo \"Hello!\""
        "some-other-command"
        info "my-task completed!"
    }
}

Memo

  • この手の後発ツールには珍しくwerkは速度を謳ってない(最速を目指しているわけではない)
    • 使いやすさが優先事項
  • 独自記法なこともあってちょっととっつきにくさは感じる
  • ビルドツールとしての側面では優秀そうなので、単純なコマンドランナーしか使わない自分には合わないかも
nappanappa

shortest

https://github.com/anti-work/shortest

  • 自然言語E2Eテストフレームワーク
  • AIによるテスト実行: Anthropic Claude APIを使用してAIがテストを実行
  • Playwrightベース
  • GitHub統合機能あり(MFA)
  • Mailosaurでメール送信のE2Eも可能

Usage

初期化

❯ npx @antiwork/shortest init

Need to install the following packages:
@antiwork/shortest@0.4.4
Ok to proceed? (y)

Setting up Shortest...
Installing @antiwork/shortest...
npm i @antiwork/shortest --save-dev

added 122 packages, changed 2 packages, and audited 204 packages in 3s

32 packages are looking for funding
  run `npm fund` for details

4 vulnerabilities (3 moderate, 1 high)

To address issues that do not require attention, run:
  npm audit fix

Some issues need review, and may require choosing
a different dependency.

Run `npm audit` for details.
✔ Dependencies installed
✔ shortest.config.ts created
✔ .env.local created (ANTHROPIC_API_KEY added)
✔ .gitignore created

Initialization complete! Next steps:
1. Update .env.local with your values
2. Create your first test file: example.test.ts
3. Run tests with: npx/pnpm test example.test.ts

ファイルとしてはこんだけ

❯ tree -a
.
├── .env.local
├── .gitignore
└── shortest.config.ts

API Keyを埋める

mv .env.local .env
❯ cat .env
# Shortest variables
ANTHROPIC_API_KEY=your_value_here

API Key

ここから取得

https://console.anthropic.com/login?selectAccount=true&returnTo=%2Fdashboard%3F

これだけだと使えないのでCreditを購入。一番下のBuidinessIDは何入れたらいいか不明。適当でいいか

Run

このような適当なテストを用意し、 shortest.config.tsbaseUrl をテスト対象のURLにしておく

import { shortest } from "@antiwork/shortest";

shortest("ログインボタンからログイン画面に遷移して");

shortest("メールアドレスとパスワードを使ってログインし、ポートフォリオ画面が表示されるか確認", {
  username: process.env.LAPARS_USERNAME,
  password: process.env.LAPARS_PASSWORD,
});

動いた。$0.3程らしい
headless: false になっているので実際にブラウザ立ち上がり、動いている様子がわかる

❯ npx shortest login.test.ts
Found 1 test file(s)
❯ login.test.ts (2)
  ● ログインボタンからログイン画面に遷移して
    ✓ passed
    ↳ 24,607 tokens ($0.08)
  ● メールアドレスとパスワードを使ってログインし、ポートフォリオ画面が表示されるか確認
    ✓ passed
    ↳ 63,884 tokens ($0.20)
  ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ 

   Tests          2 passed (2)
   Duration       88.37s
   Started at     8:48:31
   Tokens         88,491 tokens ($0.28)
  
 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

自動で工程ごとのスクショもとってくれている

e

複数回やってて気付いたがTokensが0になってる

❯ npx shortest login.test.ts
Found 1 test file(s)
❯ login.test.ts (2)
  ● ログインボタンからログイン画面に遷移して
    ✓ passed
  ● メールアドレスとパスワードを使ってログインし、ポートフォリオ画面が表示されるか確認
    ✓ passed
  ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯ 

   Tests          2 passed (2)
   Duration       27.53s
   Started at     9:04:04
   Tokens         0 tokens (≈ $0.00)
  
 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯

どうもテスト工程ごとにキャッシュがあるっぽいので、テストの指示内容が変わらなければAPI叩かずに同様の操作をするっぽい

{
  "metadata": {
    "timestamp": 1740613741441,
    "version": "1"
  },
  "test": {
    "name": "ログインボタンからログイン画面に遷移して",
    "filePath": ""
  },
  "data": {
    "steps": [
      {
        "reasoning": "Let me help execute this test case. First, I'll take a screenshot to locate the login button.",
        "action": {
          "name": "screenshot",
          "input": {
            "action": "screenshot"
          },
          "type": "tool_use"
        },
        "result": "Screenshot taken",
        "extras": {},
        "timestamp": 1740613722130
      },
      {
        "reasoning": "I can see the \"ログイン\" (Login) button in the top right corner. I'll move the cursor there and click it.",
        "action": {
          "name": "mouse_move",
          "input": {
            "action": "mouse_move",
            "coordinate": [
              1394,
              29
            ]
          },
          "type": "tool_use"
        },
        "result": "Mouse moved to (1394, 29)",
        "extras": {
          "componentStr": "<ul> <li> <a>最新のプロフィールを自動生成</a> </li> <li> <a>技術力のスコア化</a> </li> <li> <a>企業からの直接スカウト</a> </li> <li> <a>ユーザーインタビュー</a> </li> </ul>"
        },
        "timestamp": 1740613727113
      },
      {
        "reasoning": "",
        "action": {
          "name": "left_click",
          "input": {
            "action": "left_click"
          },
          "type": "tool_use"
        },
        "result": "left_click at (1394, 29)",
        "extras": {},
        "timestamp": 1740613731945
      },
      {
        "reasoning": "Let me take another screenshot to verify we've reached the login page.",
        "action": {
          "name": "screenshot",
          "input": {
            "action": "screenshot"
          },
          "type": "tool_use"
        },
        "result": "Screenshot taken",
        "extras": {},
        "timestamp": 1740613736071
      }
    ]
  }
}

このキャッシュの中身にパスワードがもろ入ってた
なんか payload も全部送ってそうなので念の為パスは変えておく