Skip to content
view raw .md

Move a task when a pull request merges

Close the loop between code and plan: find the Dailybot task key in a pull request, move the task to its board's done column and leave a comment, from any CI.

Beta

Plan is in beta. Everything under /plan in the web app, the CLI and agent skill commands for projects, goals, boards and tasks, and the /v1/plan/ public API may change before general availability. Want to try it with your team? Write to [email protected].

When a pull request titled ENG-142: Ship the delta feed merges, the task ENG-142 should move to done without anyone touching the board. Task keys make this easy: a key is enough to address a task, and every board has a column in the done category.

This recipe is a shell script you can run as the last step of any CI job after a merge.

Pick a credential

  • A personal API key (X-API-KEY) suits CI that should act as one person: it reaches everything that person can see, with no scope to request. An agent or organization key acts as a system actor instead: it only reaches tasks on organization-visible boards and needs the tasks:write scope granted to it (during the Beta, write to [email protected]).
  • A CLI user token also works if the move should be recorded as a specific person.

See Authentication for Plan.

The script

#!/usr/bin/env bash
set -euo pipefail
API="https://api.dailybot.com/v1/plan"
AUTH=(-H "X-API-KEY: $DAILYBOT_API_KEY")

# 1. Find the task key in the pull request title (or the branch name).
KEY=$(echo "$PR_TITLE" | grep -oE '[A-Z][A-Z0-9]+-[0-9]+' | head -1 || true)
if [ -z "$KEY" ]; then echo "No task key in the title; nothing to move."; exit 0; fi

# 2. Read the task by its key to learn its board and version.
TASK_JSON=$(curl -sS --fail-with-body "$API/tasks/$KEY/" "${AUTH[@]}")
BOARD=$(echo "$TASK_JSON" | jq -r .board)
VERSION=$(echo "$TASK_JSON" | jq -r .version)

# 3. Pick the board's first column in the "done" category.
DONE=$(curl -sS --fail-with-body "$API/boards/$BOARD/states/" "${AUTH[@]}" \
  | jq -r '[.[] | select(.category == "done")][0].uuid')

# 4. Move the task there, refusing if someone changed it meanwhile.
curl -sS --fail-with-body -X POST "$API/tasks/$KEY/move/" "${AUTH[@]}" \
  -H "Content-Type: application/json" \
  -H "If-Match: \"$VERSION\"" \
  -d "{\"state\": \"$DONE\"}" | jq '{key, state: .state.name, version}'

# 5. Say why it moved.
curl -sS --fail-with-body -X POST "$API/tasks/$KEY/comments/" "${AUTH[@]}" \
  -H "Content-Type: application/json" \
  -d "{\"body\": \"Merged: $PR_URL\"}" > /dev/null

Set PR_TITLE and PR_URL from your CI’s pull request variables.

Details that matter

  • Keys survive renames. If the board’s key changed from ENG to PLAT after the branch was opened, ENG-142 still resolves.
  • Categories, not names. Columns can be called anything; the done category is what makes this script work on every board.
  • Concurrent edits. If someone edited the task between the read and the move, the move answers 409 version_conflict. Re-run the step, or drop If-Match if the merge should always win.
  • Moving is the only way to change a state; the task goes to the end of the done column.
  • A key from another organization, or on a board the credential cannot see, answers 404.

From the CLI, the equivalent commands are:

dailybot plan task move "$KEY" --state done
dailybot plan task comment "$KEY" "Merged: $PR_URL"

Reference