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