main
Raw Download raw file

tissue update / tissue close / tissue reopen

Update issue metadata and status.

Tissue Commands

# Update status
tissue update 42 --status "in-progress"
tissue close 42
tissue reopen 42

# Update priority and tags
tissue update 42 --priority critical
tissue tag 42 "needs-review" "v2.0"
tissue untag 42 "wontfix"

# Add comment
tissue comment 42 "Started working on this"

Manual Workflow (bash + git)

Update issue status

# Change status field using yq
update_status() {
    ISSUE_NUM="$1"
    NEW_STATUS="$2"
    cd ../issues

    PADDED_NUM=$(printf "%03d" "$ISSUE_NUM")
    FILE=$(ls ${PADDED_NUM}_*.md 2>/dev/null | head -1)

    if [ -z "$FILE" ]; then
        echo "Issue #${ISSUE_NUM} not found"
        return 1
    fi

    # Validate status
    VALID=$(echo "$NEW_STATUS" | yq '. as $s | ["open", "in-progress", "closed", "blocked"] | contains([$s])')
    if [ "$VALID" != "true" ]; then
        echo "Invalid status: $NEW_STATUS"
        return 1
    fi

    # Update status and timestamp using yq
    yq --front-matter '
        .status = "'"$NEW_STATUS"'" |
        .updated = now
    ' -i "$FILE"

    # Commit the change
    git add "$FILE"
    git commit -m "Update issue #${ISSUE_NUM}: status -> ${NEW_STATUS}"

    echo "Issue #${ISSUE_NUM} status updated to: ${NEW_STATUS}"
}

update_status 42 "in-progress"

Close and reopen shortcuts

# Close issue
close_issue() {
    ISSUE_NUM="$1"
    update_status "$ISSUE_NUM" "closed"

    # Optionally add closing comment
    if [ -n "$2" ]; then
        add_comment "$ISSUE_NUM" "Closed: $2"
    fi
}

# Reopen issue
reopen_issue() {
    ISSUE_NUM="$1"
    update_status "$ISSUE_NUM" "open"

    # Add reopening comment
    add_comment "$ISSUE_NUM" "Reopened"
}

close_issue 42 "Fixed in commit abc123"
reopen_issue 42

Update priority

# Change priority field using yq
update_priority() {
    ISSUE_NUM="$1"
    NEW_PRIORITY="$2"
    cd ../issues

    PADDED_NUM=$(printf "%03d" "$ISSUE_NUM")
    FILE=$(ls ${PADDED_NUM}_*.md 2>/dev/null | head -1)

    if [ -z "$FILE" ]; then
        echo "Issue #${ISSUE_NUM} not found"
        return 1
    fi

    # Validate priority using yq
    VALID=$(echo "$NEW_PRIORITY" | yq '. as $p | ["low", "medium", "high", "critical"] | contains([$p])')
    if [ "$VALID" != "true" ]; then
        echo "Invalid priority. Use: low, medium, high, or critical"
        return 1
    fi

    # Update priority and timestamp
    yq --front-matter '
        .priority = "'"$NEW_PRIORITY"'" |
        .updated = now
    ' -i "$FILE"

    git add "$FILE"
    git commit -m "Update issue #${ISSUE_NUM}: priority -> ${NEW_PRIORITY}"
}

update_priority 42 "critical"

Add and remove tags

# Add tags to issue using yq
add_tags() {
    ISSUE_NUM="$1"
    shift  # Remove first argument
    NEW_TAGS="$@"
    cd ../issues

    PADDED_NUM=$(printf "%03d" "$ISSUE_NUM")
    FILE=$(ls ${PADDED_NUM}_*.md 2>/dev/null | head -1)

    if [ -z "$FILE" ]; then
        echo "Issue #${ISSUE_NUM} not found"
        return 1
    fi

    # Add each new tag using yq
    for tag in $NEW_TAGS; do
        yq --front-matter '.tags += ["'"$tag"'"]' -i "$FILE"
    done

    # Remove duplicates and update timestamp
    yq --front-matter '
        .tags |= unique |
        .updated = now
    ' -i "$FILE"

    git add "$FILE"
    git commit -m "Add tags to issue #${ISSUE_NUM}: ${NEW_TAGS}"
}

# Remove tags from issue using yq
remove_tags() {
    ISSUE_NUM="$1"
    shift
    REMOVE_TAGS="$@"
    cd ../issues

    PADDED_NUM=$(printf "%03d" "$ISSUE_NUM")
    FILE=$(ls ${PADDED_NUM}_*.md 2>/dev/null | head -1)

    if [ -z "$FILE" ]; then
        echo "Issue #${ISSUE_NUM} not found"
        return 1
    fi

    # Remove each tag using yq
    for tag in $REMOVE_TAGS; do
        yq --front-matter '.tags -= ["'"$tag"'"]' -i "$FILE"
    done

    # Update timestamp
    yq --front-matter '.updated = now' -i "$FILE"

    git add "$FILE"
    git commit -m "Remove tags from issue #${ISSUE_NUM}: ${REMOVE_TAGS}"
}

add_tags 42 "needs-review" "v2.0"
remove_tags 42 "wontfix"

Add comments to issue

# Add timestamped comment to issue body
add_comment() {
    ISSUE_NUM="$1"
    COMMENT="$2"
    cd ../issues

    PADDED_NUM=$(printf "%03d" "$ISSUE_NUM")
    FILE=$(ls ${PADDED_NUM}_*.md 2>/dev/null | head -1)

    if [ -z "$FILE" ]; then
        echo "Issue #${ISSUE_NUM} not found"
        return 1
    fi

    # Create comment with timestamp
    TIMESTAMP=$(date -u +"%Y-%m-%d %H:%M:%S UTC")
    AUTHOR=$(git config user.name)
    COMMENT_BLOCK="

### Log

**[${TIMESTAMP}] ${AUTHOR}:**
${COMMENT}"

    # Append comment to file
    if ! grep -q "^### Log" "$FILE"; then
        # Add Log section if it doesn't exist
        echo "$COMMENT_BLOCK" >> "$FILE"
    else
        # Add comment in Log section
        echo "
**[${TIMESTAMP}] ${AUTHOR}:**
${COMMENT}" >> "$FILE"
    fi

    # Update the timestamp using yq
    yq --front-matter '.updated = now' -i "$FILE"

    git add "$FILE"
    git commit -m "Add comment to issue #${ISSUE_NUM}"

    echo "Comment added to issue #${ISSUE_NUM}"
}

add_comment 42 "Started working on this issue. Found the root cause in module X."

Update assignee

# Assign issue to user using yq
assign_issue() {
    ISSUE_NUM="$1"
    ASSIGNEE="$2"
    cd ../issues

    PADDED_NUM=$(printf "%03d" "$ISSUE_NUM")
    FILE=$(ls ${PADDED_NUM}_*.md 2>/dev/null | head -1)

    if [ -z "$FILE" ]; then
        echo "Issue #${ISSUE_NUM} not found"
        return 1
    fi

    # Update assignee field using yq
    if [ -n "$ASSIGNEE" ]; then
        yq --front-matter '
            .assignee = "'"$ASSIGNEE"'" |
            .updated = now
        ' -i "$FILE"
        COMMIT_MSG="Assign issue #${ISSUE_NUM} to ${ASSIGNEE}"
    else
        yq --front-matter '
            .assignee = null |
            .updated = now
        ' -i "$FILE"
        COMMIT_MSG="Unassign issue #${ISSUE_NUM}"
    fi

    git add "$FILE"
    git commit -m "$COMMIT_MSG"
}

# Unassign issue
unassign_issue() {
    ISSUE_NUM="$1"
    assign_issue "$ISSUE_NUM" ""
}

assign_issue 42 "@alice"
unassign_issue 42

What tissue does for you:

  1. Validates field values before updating
  2. Automatically updates timestamps
  3. Maintains audit trail through git history
  4. Supports bulk operations efficiently
  5. Handles comment threading and formatting
  6. Provides shortcuts for common operations
  7. Ensures data integrity during updates
  8. Manages assignee references consistently
  9. Supports undo through git mechanisms
  10. Integrates with hooks for notifications