Sending notifications by mail when the project is deployed

    In our project, with every deploy, developers, testers and a couple of people receive wonderful letters:
    Subject: Our project version v1.1.1 is updated on the server 'testing'

    user1 posted the following updates on the server 'testing':

    Task commits:
    jira.local / browse / PROJECT-1234

    Full list of commits from the previous update:
    4392a53 Thu Aug 18 17: 50:32 2011 +0700 user1 / [PROJECT-1234] made a useful
    f2fcfe2 Thu Aug 18 17:37:53 2011 +0700 user1 / made a terrible
    cb1fcbe Wed Aug 17 15:18:10 2011 +0700 user2 / made

    changes to the files:
    file1 | 4 ++ -
    file2 | 8 ++++ ----
    file3 | 8 ++++ ----
    3 files changed, 10 insertions (+), 10 deletions (-)

    Such a solution helped us get rid of the testers' questions “Well, have they already posted the fix for bug XXX?”, “What's new on the test server?”. Also, all team members, the implementation department and the management are aware of what is happening with the code on the servers.
    For work, git, capistrano (+ multistage), php, bash (+ some console utilities) are used. If interested - go under the cat.

    Work algorithm

    • Updating the code on the testing server (cap testing deploy)
    • After deploy: restart, a hook is created that creates a tag in the repository. The tag is formed on the basis of the project version (stored in the config, in the repository), the name of the staging server and the name of the release
    • A hook is triggered in the repository. If the tag does not come, we ignore it; if the tag is:
      • We saw it into components: version, server
      • We determine the previous tag on the same server
      • If there is no tag, then this is the first installation and it’s not worth generating differences, there may be several thousand commits
      • If there is a tag, we generate a list of differences, pull out a list of tasks from them; make a list of modified files
      • Sending a generated email

    Tag creation

    About the setting of capistrano and capistrano-multistage, it’s not already written anywhere, so I’ll just tell you how we add the tag.

    We assume that we have a configs.ini file in the root of the repository that contains the runtime.version key . The basis was taken gist # 381852 .

    namespace :deploy do
    ...
      after "deploy:restart", "deploy:git:push_deploy_tag"
      namespace :git do
        desc "Place release tag into Git and push it to server."
        task :push_deploy_tag do
          user = `git config --get user.name`.strip
          email = `git config --get user.email`.strip
          version = `git cat-file -p #{real_revision}:configs.ini | fgrep runtime.version | awk -F '[ =]+' '{print $2}'`.strip
          puts `git tag v#{version}-#{stage}-#{release_name} #{real_revision} -m "Deployed by #{user} <#{email}>"`
          puts `git push --tags`
        end
      end
    end
    

    What's going on here:
    • We retrieve the current user data (name and mail) from the git config
    • We take the configs.ini file from the installed revision and pull out the version
    • Create an annotated tag. In the annotation we indicate who and when
    • Publish tags

    Processing repository update

    The pre-receive hook receives 3 values ​​at the input (stdin): previous and current revisions, refname.
    We read the incoming parameters and make sure that the tag has arrived:
    while read oldrev newrev refname
    do
        rev_type=$(git cat-file -t $newrev 2>/dev/null)
        case "$refname","$rev_type" in
            refs/tags/*,tag)
    ...
            ;;
        esac
    done
    

    Select the tag name, break it into pieces, look for the previous tag for this server:
    tag=${refname##refs/tags/}
    version=`echo $tag | cut -d- -f1`
    server=`echo $tag | cut -d- -f2`
    prevtag=$(git describe --tags --abbrev=0 --match="*-$server-*" $newrev^ 2>/dev/null)
    

    If $ prevtag is empty, then this is the first installation on the server. If the version of the new and old tags matches, this is an update; if not, the installation of a new version. Thus, we generate the correct message header.

    We begin to form the body of the letter. First, let's determine who dared to deploy:
    eval $(git for-each-ref --shell --format='
              tagger=%(taggername)
              tagged=%(taggerdate)' $refname
            )
    echo "$tagger выложил следующие обновления на сервер '$server':" > msg
    

    Now let's analyze task commits. The latter in Jira are named after the mask <project alias> -, all developers must specify the task alias (uppercase) in the commit. If the task is larger than 30 minutes and requires more than 1 commit, a branch is created according to the task alias, and then in commits we no longer mention this task. In total, in order to get a list of tasks, we need to perform not complicated processing with a regular schedule:
    git log $rev_range --abbrev-commit --pretty="format:%s" > tmpfile
    php >tickets <

    Если в итоге файл tmpfile не пуст — добавляем его к телу письма.
    Дальше идёт информация, которая интересует только разработчиков проекта: списки коммитов и изменённых файлов:
    echo "Полный список коммитов с предыдущего обновления:" >> msg
    git log $rev_range --no-merges --abbrev-commit --pretty="format:%h %ad %an / %s" >> msg
    echo -e "\n\nИзменения по файлам:" >>msg
    git diff --stat=140,110 $rev_range >>msg
    

    Ну и, наконец, тупая отправка письма:
    cat msg | mail -s "$subject" $MAIL_TO


    Все файлы можно взять на гитхабе: github.com/zvirusz/git-deploy-notify

    P.S. Если кто-нибудь поможет переписать кусок кода, выдёргивающий имена задач, на perl/bash — я буду очень рад.

    Also popular now: