Maintaining manual gitlab installation with ansible

A long time ago we started using GitLab. It was a greate step forward and definitly the right decision to switch from SVN to a distributed version control system. If you want to try GitLab you should definitly install it using GitLab Omnibus distribution.

Manual installation

But this long time ago there was no omnibus installation available so we installed GitLab with a manual git checkout. Their monthly release cycle brought some upgrade effort every month - there was an upgrade tool available which was marked as discontinued - so i started to write some anisble scripts to handle the upgrade process.

Dependencies to shell and workhorse

GitLab uses now several different modular packages as GitLab workhorse and GitLab shell which have some version dependencies, so it would be great if ansible could determine these versions from GitLab checkout itself.

Ansible gitlab role

I’ve created a gitlab role which upgrades all parts of GitLab with just one single command:

data/ansible-roles/gitlab
├── defaults
│   └── main.yml
├── handlers
│   └── main.yml
└── tasks
    ├── gitlab-shell.yml
    ├── gitlab-workhorse.yml
    ├── gitlab.yml
    └── main.yml

3 directories, 6 files

Role explained

  1. First we have to detect the installed version and compare it to required one, which is set in gitlab/tasks/defaults.yml. If version is already installed, we’re finished.

    gitlab/tasks/defaults.yml
    1
    2
    3
    4
    5
    6
    # -----------------------------------------------------------------------------
    # ATTENTION: Please strip leading `v` from version information
    # valid: 7.12.2
    # invalid: v7.12.2
    gitlab_user: git
    gitlab_version: 8.4.0
    
    gitlab/tasks/main.yml
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    ---
    - name: compare required to installed version
      command: chdir=/home/{{ gitlab_user }}/gitlab cat VERSION
      register: gitlab_installed_version
      changed_when: gitlab_installed_version.stdout != "{{ gitlab_version }}"
    
    - name: fetch remote and checkout required version
      git: repo=https://github.com/gitlabhq/gitlabhq.git
           dest=/home/{{ gitlab_user }}/gitlab
           version=v{{ gitlab_version }}
           force=yes
      sudo_user: "{{ gitlab_user }}"
    
    - name: upgrade gitlab-shell if required
      include: gitlab-shell.yml
      when: gitlab_installed_version.changed
    
    - name: upgrade gitlab-workhorse if required
      include: gitlab-workhorse.yml
      when: gitlab_installed_version.changed
    
    - name: upgrade gitlab if version changed
      include: gitlab.yml
      when: gitlab_installed_version.changed
      notify:
      - restart gitlab
      - restart apache
    
  2. Now fetch GitLab remote repository and checkout required version. installed one. If it is different to current installed one we have multiple tasks to be executed in given order.

    gitlab/tasks/gitlab.yml
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    ---
    - name: copy new init script
      shell: cp /home/{{ gitlab_user }}/gitlab/lib/support/init.d/gitlab /etc/init.d/gitlab
    
    - name: replace socket to tcp listener in init script (apache only)
      replace: dest=/etc/init.d/gitlab
               regexp='^(gitlab_workhorse_options=".+ -listenNetwork) unix (-listenAddr) \$socket_path/gitlab-workhorse\.socket (.+) -authSocket \$rails_socket (.+)$'
               replace='\1 tcp \2 127.0.0.1:8181 \3 \4'
               backup=no
    
    - name: install using bundler
      shell: chdir=/home/{{ gitlab_user }}/gitlab PATH=$PATH:/usr/pgsql-9.4/bin bundle install --deployment --without development test mysql
      sudo_user: "{{ gitlab_user }}"
    
    - name: run database migration
      shell: chdir=/home/{{ gitlab_user }}/gitlab bundle exec rake db:migrate RAILS_ENV=production
      sudo_user: "{{ gitlab_user }}"
    
    - name: recompile assets
      shell: chdir=/home/{{ gitlab_user }}/gitlab bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
      sudo_user: "{{ gitlab_user }}"
    
  3. If the version differs from current installed version, check new required shell version and checkout new shell if required.

    gitlab/tasks/gitlab-shell.yml
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    ---
    - name: read required shell version
      command: chdir=/home/{{ gitlab_user }}/gitlab cat GITLAB_SHELL_VERSION
      register: gitlab_shell_required_version
    
    - name: fetch remote and checkout required shell version
      git: repo=https://github.com/gitlabhq/gitlab-shell.git
           dest=/home/{{ gitlab_user }}/gitlab-shell
           version=v{{ gitlab_shell_required_version.stdout }}
           force=yes
      sudo_user: "{{ gitlab_user }}"
      when: gitlab_shell_required_version.changed
    
  4. If the version differs from current installed version, check new required workhorse version and checkout new workhorse if required. After checkout compile workhorse.

    gitlab/tasks/gitlab-workhorse.yml
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    ---
    - name: read required workhorse version
      command: chdir=/home/{{ gitlab_user }}/gitlab cat GITLAB_WORKHORSE_VERSION
      register: gitlab_workhorse_required_version
    
    # No semantic versioning, see: https://gitlab.com/gitlab-org/gitlab-git-http-server/issues/14
    - name: fetch remote and checkout required workhorse version
      git: repo=https://gitlab.com/gitlab-org/gitlab-workhorse.git
           dest=/home/{{ gitlab_user }}/gitlab-workhorse
           version={{ gitlab_workhorse_required_version.stdout }}
           force=yes
      sudo_user: "{{ gitlab_user }}"
      when: gitlab_workhorse_required_version.changed
    
    - name: compile workhorse
      command: make chdir=/home/{{ gitlab_user }}/gitlab-workhorse
      sudo_user: "{{ gitlab_user }}"
      when: gitlab_workhorse_required_version.changed
    
  5. Restart gitlab and apache service if a version has changed.

    gitlab/handlers/main.yml
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    ---
    - name: restart gitlab
      service:
        name: gitlab
        state: restarted
        enabled: yes
    
    - name: restart apache
      service:
        name: httpd
        state: restarted
        enabled: yes
    

Final words

Of course these formulas are specific to your setup, that’s why i did not push them into a public repo. If you use nginx as webserver, these may be different and you could use unix sockets instead of tcp listeners.

But anyway - feel free to submit your comments and reuse parts you need.

Comments

comments powered by Disqus