My First Release
Kannasaver has been released a few days ago. This was my first hand-made release ever. So what have I learned from it?
- start
- talk to people
- use a check list
- use a release script
- write the announcements beforehand
Start
Before I finally started the release preparation, I hesitated a few weeks. I felt like standing in front of something I could not handle. I did not know where to start and thus started nowhere.
One day I plucked up the courage to write a mail to kde-i18n-doc announcing the release. The point of no return. :D
I suppose I need something like this to turn my engine. And it worked.
Talk to People
Still not sure where to start, I asked Eike, the Yakuake maintainer. I remembered him using a check list for his releases which did sound like a good idea for someone as jumbled as me. In the past I also observed some releases of Yakuake to see what steps are to be done.
So, there certainly are people who already walked down the road your journey will lead you along. Ask them for pitfalls, it might save you a broken leg.
Use a Check List
So Eike gave me the check list he was using to release the latest Yakuake version. Very helpful. I never thought that releasing such a small piece of software, as Kannasaver is, would take several days. Just thinking about the actual steps does not seem to be that big a deal. However, service A does not work as expected, provider B has problems with the input form and what was the way again to upload screen shots to hoster C? All these things can take hours to solve and might force you to continue one or several days later.
That is why it is good to keep track of what has been done already and what is still in the queue. Check lists. :)
Here is my version (only minor changes to the Yakuake one).
[ ] write release announcement in all required versions [ ] select translations [ ] adjust code base for release [ ] adjust source for tarball [ ] generate tarball [ ] do build tests [ ] tag [ ] adjust code base for next dev cycle [ ] add new version in bugzilla [ ] upload tarball to kde-apps [ ] update kde-apps [ ] update sourceforge [ ] update ohloh [ ] update freshmeat [ ] update p.k.o (news) [ ] mail kde-announce-apps & kde-extra-gear
For me even almost one week after the release not all tasks are completed. It is my first release.
There is a lot to discover, some of which will throw you back in your time table.
Use a Release Script
At first I thought I should avoid release scripts for the better learning experience. It worked.
Especially deciding what translations are ready for shipping is bound to a lot of typing of long command lines that way. So after a few times of typing the same command, I put it to a file and executed it with the shell. Soon other commands followed and after two hours and a cup of tea I had my own … release script. … Oh, … dammit.
Well, making the best of the situation, I invested another hour into the script and there it is.
#!/bin/sh
set -u
#set -e
WD=$(pwd)
APP=kannasaver
VERSION="1.2"
MODULE=extragear
SUBMODULE=artwork
THRESHOLD=80
echo "== Start =="
echo
echo "== Fetching ${APP} source... =="
git clone kde:${APP}
rm -rf ${WD}/${APP}/.git
rm ${WD}/${APP}/.gitignore
rm ${WD}/${APP}/Messages.sh
echo
echo "== Patching ${APP} CMakeLists.txt... =="
echo "find_package( Msgfmt REQUIRED )" >> ${WD}/${APP}/CMakeLists.txt
echo "find_package( Gettext REQUIRED )" >> ${WD}/${APP}/CMakeLists.txt
echo "add_subdirectory( po )" >> ${WD}/${APP}/CMakeLists.txt
echo
echo "== Fetching translations which are >=${THRESHOLD}% complete... =="
for lang in $(svn cat svn://anonsvn.kde.org/home/kde/trunk/l10n-kde4/subdirs); do
test "${lang}" == "x-test" && continue
echo
echo "-- ${lang} --"
unset TRANS
unset FUZZY
unset UNTRANS
mkdir -p ${WD}/${APP}/po/${lang}
cd ${WD}/${APP}/po/${lang}
svn cat svn://anonsvn.kde.org/home/kde/trunk/l10n-kde4/${lang}/messages/${MODULE}-${SUBMODULE}/${APP}.po >${WD}/${APP}/po/${lang}/${APP}.po 2>/dev/null
if test "$?" -ne "0"; then # if svn cat fails ... next language
echo " No po file found."
rm -r ${WD}/${APP}/po/${lang}
continue
fi
STAT_STR=$(msgfmt --check --statistics -o /dev/null 2>&1 ${WD}/${APP}/po/${lang}/${APP}.po)
TRANS=$(echo ${STAT_STR}| awk '{print $1}')
if test "untranslated" == "$(echo ${STAT_STR}| awk '{print $5}')"; then
UNTRANS=$(echo ${STAT_STR}| awk '{print $4}')
else
if test "fuzzy" == "$(echo ${STAT_STR}| awk '{print $5}')"; then
FUZZY=$(echo ${STAT_STR}| awk '{print $4}')
fi
if test "untranslated" == "$(echo ${STAT_STR}| awk '{print $8}')"; then
UNTRANS=$(echo ${STAT_STR}| awk '{print $7}')
fi
fi
TRANS=${TRANS:-0}
FUZZY=${FUZZY:-0}
UNTRANS=${UNTRANS:-0}
TOTAL=$[${TRANS}+${FUZZY}+${UNTRANS}]
PERCENT=$[$[${TRANS}*100]/${TOTAL}]
if test "${PERCENT}" -ge "${THRESHOLD}"; then
echo " Included (${PERCENT}%)."
echo "file( GLOB _po_files *.po )" >> ${WD}/${APP}/po/${lang}/CMakeLists.txt
echo "GETTEXT_PROCESS_PO_FILES( ${lang} ALL INSTALL_DESTINATION \${LOCALE_INSTALL_DIR} \${_po_files} )" >> ${WD}/${APP}/po/${lang}/CMakeLists.txt
echo "add_subdirectory( ${lang} )" >> ${WD}/${APP}/po/CMakeLists.txt
LANGS+=" ${lang}"
else
echo " Not included (${PERCENT}%)."
rm -r ${WD}/${APP}/po/${lang}
fi
done
echo
echo "Languages included in the release:"
echo ${LANGS}
echo
echo "== Renaming ${WD}/${APP} to ${WD}/${APP}-${VERSION}... =="
mv ${WD}/${APP} ${WD}/${APP}-${VERSION}
echo
echo "== Creating tarball ${WD}/${APP}-${VERSION}.tar.gz... =="
cd ${WD}
tar czvf ${APP}-${VERSION}.tar.gz ${APP}-${VERSION}
echo
echo "== Finished =="
I uploaded the script to my Git scratch pad. It should (although not tested) work with all apps from git.kde.org and the output looks like the following.
== Start ==
== Fetching kannasaver source... ==
Cloning into kannasaver...
== Patching kannasaver CMakeLists.txt... ==
== Fetching translations which are >=80% complete... ==
-- af --
No po file found.
[...]
-- cs --
Included (100%).
[...]
-- fi --
Not included (40%).
[...]
-- th --
Included (96%).
[...]
Languages included in the release:
cs da de en_GB es et hu it nb nds nl pt pt_BR ru sv th uk zh_TW
== Renaming /path/to/kannasaver to /path/to/kannasaver-1.2... ==
== Creating tarball /path/to/kannasaver-1.2.tar.gz... ==
/path/to/kannasaver-1.2/
/path/to/kannasaver-1.2/CMakeLists.txt
/path/to/kannasaver-1.2/po/
/path/to/kannasaver-1.2/po/es/
/path/to/kannasaver-1.2/po/es/CMakeLists.txt
/path/to/kannasaver-1.2/po/es/kannasaver.po
/path/to/kannasaver-1.2/po/de/
/path/to/kannasaver-1.2/po/de/CMakeLists.txt
/path/to/kannasaver-1.2/po/de/kannasaver.po
[...]
== Finished ==
As an additional lesson I learned here I do want to mention, that Shell scripting is easy and fast in general but a pain in the neck in detail. However, I recommend writing shell scripts here and there just for the fun of it. :)
Write the Announcements Beforehand
Well, it was the first task on Eikes check list for Yakuake and yet, I found myself painfully slow in writing the announcements and additional texts needed to update all the websites just when the input forms were loaded. Usually writing comes easy to me but all I could think of at that time was stuff like
- ok, you test-compiled it, but … will it compile for others?
- did you forgot to delete a password in one of the files?
- what if it breaks someones computer?
- will someone sue you for publishing Japanese characters?
You get the point: I had other (not always rational) stuff on my mind and could not concentrate on writing the texts. Furthermore I was tired from all the former tasks. And I am still not done with all the websites’ announcements and changes. Stupid me. Lesson learned.
So, that’s my little contemplation on my first release. I hope that, despite my slight dramatisation *sighs*, *looks to the moon*, anyone who did not release anything yet and has to do so sometime, will be less scared of the process now. I think I learned a bit. That’s satisfying. :)
Have fun. :)

The release script seems quite cool, I think I will use it (after tailoring it to my needs). If you don’t mind of course :)
@ksmanis
Sure, feel free to use it the way it helps you. :)
If you see any issues in the way it works now, please let me know. I just fixed an issue last week … so I am sure there are more of those. :)
Dude… AWESOME script :D Just tested it, works like a charm!
Thanks. Glad you like it. :)
Hey, since I am no bash guru, I have a question for you: I set the version in CMakeLists.txt in the following fashion:
set(KCM_GRUB2_VERSION_MAJOR “0″)
set(KCM_GRUB2_VERSION_MINOR “3″)
set(KCM_GRUB2_VERSION_PATCH “6″)
Would it be possible for the script to just read these values from there, so that I update the version string in only one place? Thanks :)
Just a quick hack; there are most likely better ways to do it:
MAJ=$(grep “KCM_GRUB2_VERSION_MAJOR” CMakeLists.txt| cut -d’”‘ -f2)
MIN=$(grep “KCM_GRUB2_VERSION_MINOR” CMakeLists.txt| cut -d’”‘ -f2)
PAT=$(grep “KCM_GRUB2_VERSION_PATCH” CMakeLists.txt| cut -d’”‘ -f2)
What the cut does is it cuts the line at the double quotes and then returns the second field, which is the number. :)