Przenoszenie worklogów między zadaniami

By in
Przenoszenie worklogów między zadaniami

Niekiedy zachodzi potrzeba, aby masowo przenieść worklogi pomiędzy dwoma zadaniami. Jeśli mówimy jedynie o kilku, można to z łatwością zrobić ręcznie, ale jeśli do zmigrowania jest kilkadziesiąt czy kilkaset, potrzebna jest automatyzacja. Skrypt, który dziś przedstawię, wykona całą pracę za Was.

Jako, że Jira ani Tempo Timesheets nie posiadają funkcji masowego przenoszenia worklogów, taka operacja może być przeprowadzona jedynie w bazie danych. Wciąż możecie zagłosować za tym rozwiązaniem, mając nadzieję, że pewnego dnia zostanie wdrożone. Istnieją również pluginy, które mogą pomóc, ale nie są one darmowe. Poniższy skrypt został napisany z myślą o bazie PostgreSQL, ale możecie dostosować go do innych rodzajów baz danych. Zaczynamy.

Ważne uwagi

– Jira powinna być wyłączona przez wprowadzaniem zmian w bazie danych
– Skrypt powinien być uruchamiany z użytkownika, który ma dostępy do bazy (np. postgres)
– W pierwszej kolejności migrację należy wykonać na środowisku testowym
– Skrypt był testowany jedynie na PostgreSQL
– Aplikacja Tempo Timesheets powinna być zainstalowana i włączona

Co robi skrypt

Skrypt przenosi worklogi między zadaniami zmieniając parametr issueid w tabeli worklog dla danego worklog id. Worklogi, które mają być zmigrowane możesz znaleźć podając parametry takie, jak source_issue_key, target_issue_key, updated_date, author, worklog_body and time_worked. Przed wprowadzeniem zmian skrypt podsumuje je i zapyta o Twoje potwierdzenie. Kod skryptu mógłby być znacznie krótszy ale umieściłem komentarze i output`ów dla większego komfortu.

Możesz zapoznać się z opisem skryptu poniżej oraz/lub obejrzeć wideo zawierające kilka przykładów migracji. Cały skrypt można znaleźć w moim repozytorium. Jeśli masz pytania co do użycia skryptu, nie zwlekaj, aby je zadać: contact@jiraforthepeople.com.

Pora na kod

Na początku należy podać kilka parametrów dotyczących worklogów, które chcemy migrować. SOURCE_ISSUE_KEY oraz TARGET_ISSUE_KEY są obowiązkowe. Jeśli nie podamy żadnych innych paramtrów skrypt przeniesie wszystkie worklogi z jednego zadania do drugiego.

#Optional parameters
UPDATED_DATE=""
#worklogs updated date, you need to provide operator and enclose date in single quotes.

CREATED_DATE=""
#worklogs created date, you need to provide operator and enclose date in single quotes.

START_DATE="<='2020-12-31'"
#worklogs start date, you need to provide operator and enclose date in single quotes.

AUTHOR=""
#login of the worklog author.

WORKLOG_BODY="" 
#string that have to be in a worklog body

TIME_WORKED=""
#value in seconds

UPDATE_REMAINING_TIME=false
#set to true if you want Remaining Time Estimate (Remaining) to be updated, default to false

Zarówno klucz SOURCE_ISSUE_KEY jak i klucz TARGET_ISSUE_KEY muszą być przetłumaczone na id tych zadań. W tym celu skrypt:
– dzieli klucz zadania na (np. TEST-123) na klucz projektu (TEST) oraz numer zadania (123),
– używa klucza projektu, aby pobrać id projektu
– używa id projektu oraz numeru zadania, aby pobrać id zadania

issue_id() {
    local ISSUE_KEY=$1
    if [ ${#1} -gt 0 ] 
    then
        local PROJECT_KEY=$(echo "$ISSUE_KEY" | cut -d "-" -f 1)
        local ISSUE_NUM=$(echo "$ISSUE_KEY" | cut -d "-" -f 2)
        
        #getting target project id
        local PQUERY="SELECT id from project where pkey = '$PROJECT_KEY';"
        local PROJECT_ID=$(psql jira -XAqt -c "$PQUERY" 2> /dev/null)
            
        #getting target issue id
        local IQUERY="SELECT id from jiraissue where project = $PROJECT_ID and issuenum = $ISSUE_NUM;"
        local ISSUE_ID=$(psql jira -XAqt -c "$IQUERY" 2> /dev/null)
            
        #checking if issue with provided key existst
        if [ ${#ISSUE_ID} -eq 0 ]
        then
            echo "No issue found with key $1"
            exit 1
        fi
        echo $ISSUE_ID
    else
    echo "you need to pass TARGET_ISSUE_KEY"
    exit 1
    fi
}

#checking if the target issue was provided, if so, it needs to be translated to issue id
TARGET_ISSUE_ID="$(issue_id $TARGET_ISSUE_KEY)"
SOURCE_ISSUE_ID="$(issue_id $SOURCE_ISSUE_KEY)"

Następnie skrypt zbuduje zapytanie sql w oparciu o podane przez nas parametry.

#constructing query for getting worklog ids to migrate 
PARAMS=""
PARAMS+=" worklog.issueid = $SOURCE_ISSUE_ID "
if [ ${#UPDATED_DATE} -gt 0 ] 
    then
        PARAMS+=" and worklog.updated $UPDATED_DATE "
fi

if [ ${#CREATED_DATE} -gt 0 ] 
    then
        PARAMS+=" and worklog.created $CREATED_DATE "
fi

if [ ${#START_DATE} -gt 0 ] 
    then
	PARAMS+=" and worklog.startdate $START_DATE "
fi

if [ ${#AUTHOR} -gt 0 ] 
    then
	PARAMS+=" and worklog.author = '$AUTHOR' "
fi

if [ ${#WORKLOG_BODY} -gt 0 ] 
    then
	PARAMS+=" and worklog.worklogbody $WORKLOG_BODY "
fi

if [ ${#TIME_WORKED} -gt 0 ] 
    then
	PARAMS+=" and worklog.timeworked $TIME_WORKED "
fi

Skrypt następnie sprawdza czy istnieją worklogi do przeniesienia.

CHECK_QUERY="SELECT worklog.id from worklog INNER JOIN jiraissue on worklog.issueid = jiraissue.id INNER JOIN project on project.id = jiraissue.project where $PARAMS;"

CHECK=$(psql jira -XAqt -c "$CHECK_QUERY")
if [ -z "$CHECK" ]
    then	
	echo There are no worklogs to migrate
	exit 1
fi

Jeśli chcesz również zaktualizować wartość Remaining Estimate value w zadaniu źródłowym i docelowym skrypt zrobi to za Ciebie.

#TIMEWORKED SUM IN A SOURCE ISSUE
TIMEWORKED_QUERY="SELECT worklog.timeworked from worklog INNER JOIN jiraissue on worklog.issueid = jiraissue.id where $PARAMS;"
TIMEWORKED_QUERY_EXECUTION=$(psql jira -XAqt -c "$TIMEWORKED_QUERY")
TIMEWORKED_ARR=($TIMEWORKED_QUERY_EXECUTION)

for t in "${TIMEWORKED_ARR[@]}"; do
    TIMEWORKED_SUM=$((TIMEWORKED_SUM+t))
done

#TIMESPENT SUM IN A SOURCE ISSUE
TIMESPENT_SOURCE_QUERY="SELECT timespent from jiraissue where id = $SOURCE_ISSUE_ID;"
TIMESPENT_SOURCE_SUM=$(psql jira -XAqt -c "$TIMESPENT_SOURCE_QUERY")
NEW_TIMESPENT_SOURCE_SUM=$(($TIMESPENT_SOURCE_SUM-$TIMEWORKED_SUM))

#TIMESPENT SUM IN A TARGET ISSUE
TIMESPENT_TARGET_QUERY="SELECT timespent from jiraissue where id = $TARGET_ISSUE_ID;"
TIMESPENT_TARGET_SUM=$(psql jira -XAqt -c "$TIMESPENT_TARGET_QUERY")
NEW_TIMESPENT_TARGET_SUM=$(($TIMESPENT_TARGET_SUM+$TIMEWORKED_SUM))

if [ $UPDATE_REMAINING_TIME = true ]
    then
	TIMEESTIMATE_SOURCE_QUERY="SELECT timeestimate from jiraissue where id = $SOURCE_ISSUE_ID;"
	TIMEESTIMATE_QUERY_SOURCE_EXECUTION=$(psql jira -XAqt -c "$TIMEESTIMATE_SOURCE_QUERY")

	if [ -z "$TIMEESTIMATE_QUERY_SOURCE_EXECUTION" ]
	    then
		TIMEESTIMATE_QUERY_SOURCE_EXECUTION=0
	fi

	NEW_TIMEESTIMATE_SOURCE_SUM=$(($TIMEESTIMATE_QUERY_SOURCE_EXECUTION+$TIMEWORKED_SUM))			
        TIMEESTIMATE_TARGET_QUERY="SELECT timeestimate from jiraissue where id = $TARGET_ISSUE_ID;"
	TIMEESTIMATE_QUERY_TARGET_EXECUTION=$(psql jira -XAqt -c "$TIMEESTIMATE_TARGET_QUERY")

	if [ -z "$TIMEESTIMATE_QUERY_TARGET_EXECUTION" ]
	     then
		TIMEESTIMATE_QUERY_TARGET_EXECUTION=0
	fi
		
	NEW_TIMEESTIMATE_TARGET_SUM=$(($TIMEESTIMATE_QUERY_TARGET_EXECUTION-$TIMEWORKED_SUM))

	#if new time estimate is less than 0, it stays at 0 value
	if [ $NEW_TIMEESTIMATE_TARGET_SUM -lt 0 ] 
	    then
		NEW_TIMEESTIMATE_TARGET_SUM=0
	fi		
fi

Wreszcie, dostajemy podsumowanie wprowadzanych zmian czekające na potwierdzenie.

#confirmation: script summarizes changes before applying them and waits for your confirmation
echo "Worklog params: $PARAMS"

TQUERY="SELECT worklog.id as worklog_id,worklog.issueid as issue_id,worklog.author as worklog_author,worklog.startdate::date as start_date,worklog.updated::date as updated_date,worklog.created::date as created_date,worklog.timeworked,concat(project.pkey, '-', jiraissue.issuenum) as issuekey from worklog INNER JOIN jiraissue on worklog.issueid = jiraissue.id INNER JOIN project on project.id = jiraissue.project where $PARAMS;"

CONFIRMATION_QUERY=$(psql jira -XAq -c "$TQUERY")
echo "Following worklog entries will be moved from $SOURCE_ISSUE_KEY to $TARGET_ISSUE_KEY."

#converting query to array which makes output more readable
CONF_ARR=($CONFIRMATION_QUERY)
for w in "${CONF_ARR[@]}"; do
	echo $w
done

read -p "Do you want to move worklogs from $SOURCE_ISSUE_KEY to $TARGET_ISSUE_KEY (y/n)?" -n 1 -r

I czas na migrację.

if [[ $REPLY =~ ^[yY]$ ]]
    #getting worklogs ids after your confirmation
    then

	#updating source issue timespent
	TIMESPENT_SOURCE_UPDATE_QUERY="UPDATE jiraissue set timespent = $NEW_TIMESPENT_SOURCE_SUM where id = $SOURCE_ISSUE_ID"
	psql jira -XAqt -c "$TIMESPENT_SOURCE_UPDATE_QUERY" 2> /dev/null
	
	#updating target issue timespent
	TIMESPENT_TARGET_UPDATE_QUERY="UPDATE jiraissue set timespent = $NEW_TIMESPENT_TARGET_SUM where id = $TARGET_ISSUE_ID"
	psql jira -XAqt -c "$TIMESPENT_TARGET_UPDATE_QUERY" 2> /dev/null

	#updating remaining timeestimate
	if [ $UPDATE_REMAINING_TIME = true ]
	    then 
		#updating target issue remaining estimate
		TIMEESTIMATE_TARGET_UPDATE_QUERY="UPDATE jiraissue set timeestimate = $NEW_TIMEESTIMATE_TARGET_SUM where id = $TARGET_ISSUE_ID"
		psql jira -XAqt -c "$TIMEESTIMATE_TARGET_UPDATE_QUERY" 2> /dev/null
			
		#updating source issue remaining estimate
		TIMEESTIMATE_SOURCE_UPDATE_QUERY="UPDATE jiraissue set timeestimate = $NEW_TIMEESTIMATE_SOURCE_SUM where id = $SOURCE_ISSUE_ID"
		psql jira -XAqt -c "$TIMEESTIMATE_SOURCE_UPDATE_QUERY" 2> /dev/null
	fi
	
        WQUERY="SELECT id from worklog where $PARAMS;"
	WORKLOG_IDS=$(psql jira -XAqt -c "$WQUERY" 2> /dev/null)
	WORKLOGS_ARR=($WORKLOG_IDS)
	
	#moving worklogs to another issue
	for w in "${WORKLOGS_ARR[@]}"; do
		UQUERY="UPDATE worklog set issueid = $TARGET_ISSUE_ID where id = $w;"
		psql jira -XAqt -c "$UQUERY" 2> /dev/null
	done

echo "Worklogs migration complete!"
fi

Leave a reply

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *