Instalación y configuración de Redmine en openSUSE

Con esta guía aprenderemos a instalar y a configurar Redmine en openSUSE, que es una herramienta web concebida para gestionar proyectos y tareas de cualquier índole, orientada principalmente a entornos colaborativos de trabajo.

Su amplio catálogo de funcionalidades y características la convierte probablemente en una de las herramientas de su tipo más completa, integrada y sencilla de uso libre que he encontrado y probado hasta el momento.

Es excelente para gestionar múltiples proyectos de desarrollo, permite administrar tareas (Peticiones), agregar wiki's, documentos, archivos, tiene soporte para foros y posee varios plugins y themes que permiten ampliar muchísimo las funcionalidades y las características de la herramienta. La misma también permite la integración de varios SCM's entre los cuales se encuentran soportados Subversion, CVS, Git, Bazaar, Mercurial y Darcs.

Redmine se encuentra desarrollado con el framework Ruby on Rails (RoR) y posee una comunidad muy grande y activa. Para más información les recomiendo visitar su sitio web redmine.org.

Más adelante se tratarán los siguientes puntos:
  • Instalación y configuración básica de la herramienta Redmine para su ejecución mediante Apache.
  • Configuración para el envío de notificaciones mediante correos electrónicos a usuarios de Redmine.
  • Generación de tareas o peticiones a partir de correos electrónicos.
  • Asociación de cuentas de correos a las tareas generadas a partir de correos electrónicos.
  • Instalación del plugin Redmine CC Addresses.
  • Configuración para integrar el SCM Subversión en Redmine.
  • Configuración de logs.
  • Implementación de copias de seguridad.
  • Instalación de nuevos temas (themes).


Instalación y configuración básica

  1. Para comenzar debemos instalar y configurar de forma básica el motor de base de datos PostgreSQL, que por cierto ya ha sido tratado en un artículo anterior y que lo pueden encontrar en el resumen de guías del blog.

  2. Mediante el comando zypper y gem instalamos algunas de las dependencias que necesita la herramienta.
    testsrv:~ # zypper in apache2 apache2-prefork ImageMagick gcc git ruby rubygems rubygem-rack rubygem-rake rubygem-postgres rubygem-passenger rubygem-passenger-apache2 rubygem-passenger-nginx rubygem-rmagick
    testsrv:~ # gem install rdoc
    
    Si no pudimos instalar el módulo passenger mediante zypper, con el gestor de paquetes de Ruby gem podemos instalalo de la siguiente forma.
    testsrv:~ # gem install passenger
    testsrv:~ # exec passenger-install-apache2-module
    
  3. Ahora toca crear en el motor de base de datos PostgreSQL un nuevo usuario y la base de datos para la herramienta Redmine, esto lo podemos hacer ejecutando los siguientes comandos
    testsrv:~ # su postgres -c psql postgres
    postgres=# CREATE ROLE redmine LOGIN ENCRYPTED PASSWORD 'redmine' NOINHERIT VALID UNTIL 'infinity';
    postgres=# CREATE DATABASE redmine WITH ENCODING='UTF8' OWNER=redmine;
    postgres-# \q
    
  4. A continuación procedemos a descargar la herramienta desde su sitio web en el directorio /opt para luego descomprimirla en el mismo directorio:
    testsrv:/opt # cd /opt/
    testsrv:/opt # wget http://rubyforge.org/frs/download.php/75597/redmine-1.3.0.tar.gz
    testsrv:/opt # tar -xzf redmine-1.3.0.tar.gz
    testsrv:/opt # rm redmine-1.3.0.tar.gz
    testsrv:/opt # mv redmine-1.3.0 redmine
    testsrv:/opt # cd redmine/
    testsrv:/opt/redmine #
    
  5. Una vez dentro del directorio raíz de la herramienta nos dirigimos a la carpeta config para crear y editar el archivo de configuración database.yml.
    testsrv:/opt/redmine # cd config/
    testsrv:/opt/redmine/config # cp database.yml.example database.yml
    testsrv:/opt/redmine/config # vi database.yml
    
    Al cual le agregamos la configuración adecuada del motor de base de datos que utilizará Redmine
    production:
      adapter: postgresql
      database: redmine
      host: localhost
      username: redmine
      password: redmine
      encoding: utf8
    
  6. Una vez concluido con el paso anterior ya podemos crear el esquema de base de datos de Redmine en PostgreSQL y cargar los registros de configuración por defecto en las tablas mediante la siguiente secuencia de comandos:
    testsrv:/opt/redmine/config # cd ..
    testsrv:/opt/redmine # rake generate_session_store
    testsrv:/opt/redmine # RAILS_ENV=production rake db:migrate
    testsrv:/opt/redmine # RAILS_ENV=production rake redmine:load_default_data
    (in /opt/redmine)
    
    Select language: bg, bs, ... en, en-GB, es, ... vi, zh, zh-TW [en] es
    ====================================
    Default configuration data loaded.
    
  7. Finalmente aplicamos los permisos, el usuario y grupo adecuados para algunos directorios de la herramienta.
    testsrv:/opt/redmine # chown -Rf wwwrun:www files log tmp public/plugin_assets
    testsrv:/opt/redmine # chmod -Rf 755 files log tmp public/plugin_assets
    


Configuración de Apache

  1. Lo primero que debemos hacer es habilitar el módulo passenger de Ruby para que Apache pueda ejecutar la herramienta web Redmine. Si hemos logrado instalar el módulo passenger mediante zypper entonces podemos activar el módulo en Apache editando primeramente el archivo /etc/sysconfig/apache2,
    testsrv:~ # vi /etc/sysconfig/apache2
    
    Para luego buscar en él la directiva APACHE_MODULES y agregar el módulo passenger al final como ya se había visto en un artículo anterior.
    APACHE_MODULES="actions alias ... rewrite passenger"
    
    Ahora bien, si hemos instalado el paquete mediante el gestor de paquetes de Ruby lo anterior no funcionará y tendremos que seguir los siguientes pasos: Primeramente debemos dirigirnos al directorio /etc/apache2/conf.d,
    testsrv:~ # cd /etc/apache2/conf.d
    
    Agregar y editar un nuevo archivo llamado passenger.conf:
    testsrv:/etc/apache2/conf.d # touch passenger.conf
    testsrv:/etc/apache2/conf.d # vi passenger.conf
    
    Y agregarle un contenido similar a lo que sigue para que Apache levante el módulo correspondiente:
    # Carga del modulo passenger en Apache.
    LoadModule passenger_module /usr/lib/ruby/gems/1.8/gems/passenger-3.0.11/ext/apache2/mod_passenger.so
    PassengerRoot /usr/lib/ruby/gems/1.8/gems/passenger-3.0.11
    PassengerRuby /usr/bin/ruby
    
  2. (OPCIÓN 1) ACCESO MEDIANTE VIRTUAL HOSTS: Si deseamos que Apache sirva el sitio web de Redmine a través de un nombre de dominio totalmente cualificado (FQDN: Fully Qualified Domain Name) resuelto a través de servidores de nombres (DNS) internos o externos podemos configurar un host virtual para dicho fin. Para ello nos dirigimos al directorio /etc/apache2/vhosts.d y creamos un nuevo archivo llamado vhost.conf:
    testsrv:~ # cd /etc/apache2/vhosts.d
    testsrv:/etc/apache2/vhosts.d # touch vhost.conf
    Editamos el archivo con nuestro editor de texto preferido..
    testsrv:/etc/apache2/vhosts.d # vi vhost.conf
    
    Y luego agregamos las siguientes directivas:
    # -- ES NECESARIO DEFINIR LA DIRECTIVA NameVirtualHost CUANDO
    # SE CONFIGURAN HOSTS VIRTUALES BASADOS EN NOMBRES.
    NameVirtualHost *:80
    
    # -- CONFIGURACION DEL HOST VIRTUAL POR DEFECTO, QUE APUNTA
    # A LA RUTA TRADICIONAL.
    <VirtualHost *:80>
        ServerName testsrv
        ServerAlias testsrv *.testsrv
        DocumentRoot /srv/www/htdocs
    </VirtualHost>
    
    # -- CONFIGURACION DEL VIRTUAL HOST PARA REDMINE
    <VirtualHost *:80>
        Options +Indexes
        ServerAdmin nombre_usuario@gmail.com
        ServerName redmine
        ServerAlias redmine.mi_dominio.local *.redmine.mi_dominio.local redmine *.redmine
        DocumentRoot /opt/redmine/public
        RailsEnv production
    
        <Directory "/opt/redmine/public">
            Options Indexes FollowSymLinks
            AllowOverride All
            Order allow,deny
            Allow from all
            Options -MultiViews
        </Directory>
    </VirtualHost>
    
    Con esto ya tenemos el servidor web configurado con soporte virtual host.

  3. (OPCIÓN 2) ACCESO MEDIANTE SUBDIRECTORIOS: Una opción alternativa a la configuración de host virtual de Apache para desplegar Redmine es utilizar una configuración más tradicional definiendo el acceso a dicha herramienta a través de un subdirectorio posterior al dominio o dirección IP de nuestro servidor web.

    Como primer paso nos dirigimos al directorio /etc/apache2/conf.d, para luego crear y editar un nuevo archivo llamado redmine.conf:
    testsrv:~ # cd /etc/apache2/conf.d
    testsrv:/etc/apache2/conf.d # touch redmine.conf
    testsrv:/etc/apache2/conf.d # vi redmine.conf
    
    Al que le agregamos la siguiente configuración:
    # -- ALIAS DEL SUBDIRECTORIO APUNTANDO A LA RUTA REAL DE
    # LA HERRAMIENTA REDMINE.
    Alias /redmine /opt/redmine/public
    
    # -- DEFINICION DEL ENTORNO RAILS.
    RailsEnv production
    RailsBaseURI /redmine
    
    # -- CONFIGURACIONES DEL DIRECTORIO DE TRABAJO.
    <Directory "/opt/redmine/public">
        Options -MultiViews +FollowSymLinks +SymLinksIfOwnerMatch
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>
    
    Una vez afuera del archivo anterior creamos un enlace simbólico del directorio /opt/redmine/public al directorio /srv/www/htdocs:
    testsrv:/etc/apache2/conf.d # ln -s /opt/redmine/public/ /srv/www/htdocs/redmine
    
  4. Finalmente activamos los niveles de ejecución y luego iniciamos (o reiniciamos si ya se estaba ejecutando) el servicio apache2:
    testsrv:~ # chkconfig --add apache2
    testsrv:~ # service apache2 start
    


Configuración del cortafuegos

  1. Para que podamos acceder a la herramienta desde otro equipo remoto necesitamos abrir los puertos HTTP (80) y HTTPS (443) en el firewall del servidor, para ello editamos el archivo SuSEfirewall2 del directorio /etc/sysconfig:
    testsrv:~ # vi /etc/sysconfig/SuSEfirewall2
    y le asignamos los servicios apache2 y apache2-ssl a la directiva FW_CONFIGURATIONS_EXT como se muestra a continuación:
    FW_CONFIGURATIONS_EXT="sshd apache2 apache2-ssl"
  2. Luego reiniciamos el cortafuegos para que la nueva configuración tome efecto, lo realizamos con el siguiente comando:
    testsrv:~ # rcSuSEfirewall2 restart


Acceso a Redmine

  1. Si para acceder a la herramienta Redmine hemos configurado el servicio Apache con virtual hosts, entonces debemos utilizar el nombre de dominio totalmente cualificado que hemos definido y que debe ser correctamente resuelto por algún servidor DNS o mediante alguna entrada al archivo /etc/hosts en la máquina cliente que se trata de conectar a la herramienta. Como ejemplo podríamos tener la siguiente URL:
    http://redmine.mi_dominio.local
    
  2. Si en el caso contrario hemos configurado el acceso a la herramienta Remine mediante un subdirectorio en Apache, la URL deberá ser similar a la siguiente:
    http://ip_o_nombre_dominio_servidor/redmine
    
    Por defecto la herramienta se ve así:
    OBS: El usuario administrador es "admin", y por defecto viene con la contraseña "admin".

    Pero hay que seguir leyendo porque más adelante podemos lograr que la misma se vea de la siguiente forma:
  3. Ventana de conexión de Redmine del theme Pixel Cookers


Configuración para envío de correos

Para que la herramienta pueda generar notificaciones vía email se tiene que definir como mínimo un servidor smtp que nos permita enviar los correos. Los pasos van a continuación:
  1. Primeramente nos dirigimos al directorio /opt/redmine/config y creamos el archivo configuration.yml a partir del archivo plantilla del mismo directorio.
    testsrv:~ # cd /opt/redmine/config/
    testsrv:/opt/redmine/config # cp configuration.yml.example configuration.yml
    
  2. Luego editamos el archivo configuration.yml,
    testsrv:/opt/redmine/config # vi configuration.yml
    
    y lo configuramos similar a lo que sigue en el caso de que tengamos un servidor de correo local:
    default:
    email_delivery:
    delivery_method: :smtp
    smtp_settings:
    address: ip_servidor_local
    port: 25
    domain: midominio.com
    authentication: :none
    
    Para una cuenta de gmail la configuración podría ser similar a lo que sigue:
    default:
    email_delivery:
    delivery_method: :smtp
    smtp_settings:
    tls: true
    enable_starttls_auto: true
    address: "smtp.gmail.com"
    port: 587
    domain: "smtp.gmail.com" # 'your.domain.com' for GoogleApps
    authentication: :plain
    user_name: "your_email@gmail.com"
    password: "your_password"
    
  3. Reiniciamos el servicio Apache para que la configuración anterior tome efecto:
    testsrv:/opt/redmine/config # service apache2 restart
    
  4. Y finalmente realizamos las configuraciones faltantes en la opción de configuración Administración-->Configuración-->Notificaciones por correo de la interfaz web de Redmine.


Registro de tareas a partir de correos electrónicos

En esta parte de la guía se van a abarcar las configuraciones y modificaciones que se necesitan realizar para implementar la generación de tareas (peticiones) a partir de correos electrónicos, su correspondiente identificación y la generación de notificaciones automáticas para la cuenta de correo que haya enviado la tarea.
  1. Para recibir los correos entrantes primero necesitamos tener una cuenta de correo definida en algún servidor local o proveedor de correo electrónico externo que permita el acceso mediante los protocolos pop3 o imap.

  2. Una vez resuelto el paso anterior podemos generar las tareas a partir de los correos que se encuentran en la bandeja de entrada dirigiéndonos al directorio /opt/redmine,
    testsrv:~ # cd /opt/redmine
    
    y ejecutando el siguiente comando que lo tenemos que adecuar a nuestras necesidades:
    testsrv:/opt/redmine # rake redmine:email:receive_imap RAILS_ENV="production" host=ip_dominio_servidor_correo port=993 username=redmine@midominio.com password=passwd_correo ssl=1 project=prueba tracker=Soporte allow_override=project,tracker,priority unknown_user=accept no_permission_check=1 move_on_success=read move_on_failure=failed
    
    En este caso se utiliza de ejemplo una cuenta de correo con acceso IMAP. Las directivas de configuración relacionadas al protocolo IMAP son las siguientes:
    host=HOST                IMAP server host (default: 127.0.0.1)
    port=PORT                IMAP server port (default: 143)
    ssl=SSL                  Use SSL? (default: false)
    username=USERNAME        IMAP account
    password=PASSWORD        IMAP password
    folder=FOLDER            IMAP folder to read (default: INBOX)
    move_on_success=MAILBOX  move emails that were successfully received
    to MAILBOX instead of deleting them
    move_on_failure=MAILBOX  move emails that were ignored to MAILBOX
    
    Por su parte, los argumentos que permiten controlar la forma en que se agrega una nueva tarea en Redmine a partir de un correo se muestran a continuación:
    project=PROJECT          identifier of the target project
    tracker=TRACKER          name of the target tracker
    category=CATEGORY        name of the target category
    priority=PRIORITY        name of the target priority
    allow_override=ATTRS     allow email content to override attributes
    specified by previous options ATTRS is a
    comma separated list of attributes
    unknown_user=ACTION
    no_permission_check=[0|1]
    
    Según como se haya definido la directiva unknown_user se puede aceptar o no correos de usuarios no registrados en Redmine para crear tareas o peticiones a partir de ellos. En nuestro comando anterior hemos utilizado la opción unknown_user=accept, que permite generar tareas a partir de correos cuyas cuentas de usuario no corresponden a un usuario de Redmine debidamente registrado.

    A continuación se muestran todas las opciones disponibles para la directiva unknown_user:
    unknown_user=ACTION     how to handle emails from an unknown user
    where ACTION can be one of the following
    values:
    - ignore: the email is ignored (default)
    - accept: the sender is considered as an anonymous user and the
    email is accepted
    - create: a user account is created for the sender (username/
    password are sent back to the user) and the email is
    accepted
    
    Para que los usuarios no registrados puedan agregar tareas vía e-mail sin problemas no basta con solo agregar la directiva unknown_user=accept, también debemos agregar la directiva no_permission_check=1 que evitará que redmine:email:receive_imap verifique los permisos relacionados al usuario Anonymous, que es el usuario de Redmine al cual serán asociadas las nuevas tareas generadas.

    Ahora bien, es importante aclarar que si queremos utilizar la directiva unknown_user=accept sin especificar la directiva no_permission_check=1 será necesario configurar los permisos del rol Anonymous, al cual tendremos que agregar el permiso "notificaciones" (add issues), y dependiendo si los proyectos son públicos o privados también habrá que configurar la "Visibilidad de las peticiones" (Issues visibility), configuraciones que además darán permisos a los usuarios anónimos para que puedan registrar tareas mediante la interfaz web de Redmine.

  3. El siguiente paso consiste en registrar una nueva tarea programada que se encargue de buscar los correos periódicamente. Para ello creamos un archivo llamado redmine dentro del directorio /etc/cron.d y luego lo editamos:
    testsrv:~ # touch /etc/cron.d/redmine
    testsrv:~ # vi /etc/cron.d/redmine
    
    Una vez abierto el archivo le agregamos la siguiente directiva que ejecuta cada minuto una versión derivada del script tratado en el paso anterior, que realizará la búsqueda de nuevos correos entrantes y creará nuevas peticiones (issues) a partir de ellos.
    # Generacion de tareas a partir de correos entrantes.
    * * * * * root rake -f /opt/redmine/Rakefile --silent redmine:email:receive_imap RAILS_ENV="production" host=ip_dominio_servidor_correo port=993 username=redmine@midominio.com password=passwd_correo ssl=1 project=prueba tracker=Soporte allow_override=project,tracker,priority unknown_user=accept no_permission_check=1 move_on_success=read move_on_failure=failed
    
    Finalmente reiniciamos el servicio cron para activar la tarea.
    testsrv:~ # service cron restart
    
  4. Si hemos utilizado las directivas unknown_user=accept y no_permission_check=1, las nuevas peticiones recibidas mediante correos serán registradas en Redmine con el usuario Anónimo como titular de la tarea, con lo cual ya no sabremos quien ha sido el real emisor del correo/tarea.

    Para evitar esto podemos realizar algunas modificaciones para que la cuenta de correo del emisor sea agregada en el título y en el cuerpo de la tarea. Para lograr esto vamos a modificar parte del código en el archivo mail_handler.rb ubicado en el directorio /opt/redmine/app/models, que se encarga de procesar los correos entrantes:
    testsrv:~ # vi /opt/redmine/app/models/mail_handler.rb
    
    Una vez abierto el archivo tenemos que buscar la siguiente sección en la cual procedemos a comentar el código que aparece en las líneas 12 y 17. Luego agregamos debajo de las líneas comentadas el código que aparece en las líneas 13 y 18 respectivamente.
    # Creates a new issue
    def receive_issue
    project = target_project
    # check permission
    unless @@handler_options[:no_permission_check]
    raise UnauthorizedAction unless user.allowed_to?(:add_issues, project)
    end
    
    issue = Issue.new(:author => user, :project => project)
    issue.safe_attributes = issue_attributes_from_keywords(issue)
    issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
    #issue.subject = email.subject.to_s.chomp[0,255]
    issue.subject = email.subject.to_s.chomp[0,255] + " (#{email.from_addrs.to_a.first.local})"
    if issue.subject.blank?
    issue.subject = '(no subject)'
    end
    #issue.description = cleaned_up_text_body
    issue.description = "ENVIADO POR: #{email.from}\r\n\r\n" + cleaned_up_text_body
    
    # add To and Cc as watchers before saving so the watchers can reply to Redmine
    add_watchers(issue)
    issue.save!
    add_attachments(issue)
    logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info
    issue
    end
    
  5. Para hacer que aquellos usuarios que envíen sus correos a soporte y que no se encuentren registrados en la herramienta Redmine reciban una notificación por cada actualización que se realice a la tarea, yo recomiendo utilizar el pluggin redmine_cc_addresses. Este plugin permite a ciertos usuarios de Redmine (según los permisos del usuario) asociar cuentas de correos a una tarea, a fin de que la herramienta envíe automáticamente notificaciones a dichas cuentas para mantener informado al interesado ante cualquier cambio que pueda sufrir la mencionada petición, como ser una asignación de técnico, cierre de tarea, etc.

    Para implementar el plugin nos dirigimos al directorio de plugins de Redmine y lo descargamos de Github de la siguiente manera:
    testsrv:~ # cd /opt/redmine/vendor/plugins/
    testsrv:/opt/redmine/vendor/plugins # git clone http://github.com/peelman/redmine_cc_addresses.git
    
    Una vez descargado el plugin debemos volver al directorio raiz de Redmine y ejecutar un comando que implementa las modificaciones requeridas por el plugin en la base de datos y en la aplicación.
    testsrv:/opt/redmine/vendor/plugins # cd /opt/redmine
    testsrv:/opt/redmine # rake db:migrate_plugins RAILS_ENV="production"
    
    Y finalmente reiniciamos el servicio Apache para que el nuevo plugin se active:
    testsrv:~ # service apache2 restart
    
    Hay que tener en cuenta que en la sección de Configuración -> Módulo de cada proyecto hay que activar el módulo CC addresses para que la sección CC Addresses aparezca en cada una de las peticiones (issues). Aparte de ello no tenemos que olvidarnos de definir los permisos correspondientes en los perfiles de usuario que podrán ver, agregar y eliminar las cuentas de correo de la lista, esto se personaliza en Administración -> Perfiles y permisos -> Perfil X.

    ATENCIÓN - OPCIONAL: Dependiendo del theme utilizado en Redmine, se ha identificado un pequeño bug del plugin en la ventana de peticiones, en el que se muestra muy grande la imagen del botón de eliminación de las listas de correos que se hayan agregado a una tarea. Si tienen este inconveniente yo lo he solucionado de la siguiente manera: realicé una copia de seguridad y procedí a editar el archivo _list.html.erb ubicado en el directorio del plugin:
    testsrv:~ # cd /opt/redmine/vendor/plugins/redmine_cc_addresses/app/views/issues/cc_addresses
    testsrv:/opt/redmine/vendor/plugins/redmine_cc_addresses/app/views/issues/cc_addresses # cp _list.html.erb _list.html.erb.orig
    testsrv:/opt/redmine/vendor/plugins/redmine_cc_addresses/app/views/issues/cc_addresses # vi _list.html.erb
    
    Una vez dentro del archivo buscamos la línea de
    image_tag('delete.png')
    
    y la reemplazamos directamente por lo siguiente
    image_tag('Eliminar')
    
    Con esto logramos que directamente aparezca el texto Eliminar en vez de la imagen que se sobre-redimenciona automáticamente. Yo se que no es una solución muy elegante, funciona, pero si hay una mejor forma de corregirlo les agradecería que lo comentaran.

  6. En las tareas generadas a partir de correos electrónicos, sería interesante agregar automáticamente a la lista de direcciones CC implementadas mediante el plugin redmine_cc_addresses las cuentas de correo del emisor y de los destinatarios con copia (CC), para que los mismos puedan mantenerse informados de los cambios que vayan surgiendo en la tarea.

    Para implementar esta funcionalidad tenemos que modificar el código del archivo mail_handler.rb
    testsrv:~ # vi /opt/redmine/app/models/mail_handler.rb
    
    Luego nos tenemos que posicionar entre los métodos add_attachments y add_watchers para agregar un nuevo método llamado add_cc_addresses, que se encargará de registrar los correos del emisor y de los asociados como CC a la lista de direcciones CC de la tarea. El código va resaltado a continuación:
    def add_attachments(obj)
    ...
    end
    
    # Metodo que agrega a la lista de correo CC de la peticion las cuentas del emisor
    # y de los asociados como copia (CC).
    def add_cc_addresses(obj)
    addresses = [email.from, email.cc].flatten.compact.uniq.collect {|a| a.strip.downcase}
    unless addresses.empty?
    addresses.each do |address|
    # Agrega a la tabla cc_addresses los correos.
    addr = CcAddress.create(:mail => address,
    :issue_id => obj.id)
    end
    end
    end
    
    # Adds To and Cc as watchers of the given object if the sender has the
    # appropriate permission
    def add_watchers(obj)
    .....
    end
    
    A continuación buscamos el método receive_issue y agregamos el código necesario para que por cada nuevo correo entrante que se procese se ejecute el método add_cc_addresses:
    # Creates a new issue
    def receive_issue
    project = target_project
    # check permission
    unless @@handler_options[:no_permission_check]
    raise UnauthorizedAction unless user.allowed_to?(:add_issues, project)
    end
    
    issue = Issue.new(:author => user, :project => project)
    issue.safe_attributes = issue_attributes_from_keywords(issue)
    issue.safe_attributes = {'custom_field_values' => custom_field_values_from_keywords(issue)}
    #issue.subject = email.subject.to_s.chomp[0,255]
    issue.subject = email.subject.to_s.chomp[0,255] + " (#{email.from_addrs.to_a.first.local})"
    if issue.subject.blank?
    issue.subject = '(no subject)'
    end
    #issue.description = cleaned_up_text_body
    issue.description = "ENVIADO POR: #{email.from}\r\n\r\n" + cleaned_up_text_body
    
    # add To and Cc as watchers before saving so the watchers can reply to Redmine
    add_watchers(issue)
    issue.save!
    add_cc_addresses(issue)
    add_attachments(issue)
    logger.info "MailHandler: issue ##{issue.id} created by #{user}" if logger && logger.info
    issue
    end
    
    Y con esto ya se agregan automáticamente por cada correo recibido las cuentas del emisor y CC a la lista de notificación de la petición o tarea de Redmine generada por el script mail_handler.rb.


Configuración SCM (Subversion)

Si bien Redmine soporta la integración de varias herramientas SCM como Subversion, CVS, Git, Bazaar, Mercurial y Darcs, en esta sección solo se abarcarán los pasos necesarios para integrar repositorios Subversion a la herramienta.
  1. Lo primero que tenemos que hacer es crear un directorio dentro del directorio home de Redmine para almacenar los proyectos y repositorios de Subversion:
    testsrv:~ # mkdir /opt/redmine/svn
    testsrv:~ # chown -Rf wwwrun:www /opt/redmine/svn
    testsrv:~ # chmod -Rf 750 /opt/redmine/svn
    
  2. Luego tenemos que instalar en openSUSE los paquetes relacionados a Subversion y otros requisitos más:
    testsrv:~ # zypper in subversion-server neon rubygem-activeresource perl-Apache-DBI perl-DBD-Pg
    
  3. Verificamos que en el archivo /etc/sysconfig/apache2 se encuentren activos los módulos perl, dav y dav_svn para Subversion.
    testsrv:~ # vi /etc/sysconfig/apache2
    
    APACHE_MODULES="actions alias ... passenger perl dav dav_svn"
    
  4. Necesitamos crear un enlace simbólico en el directorio /usr/lib/perl5/vendor_perl/5.12.3/Apache a partir del archivo Redmine.pm que se encuentra ubicado en la ruta /opt/redmine/extra/svn:
    testsrv:~ # ln -s /opt/redmine/extra/svn/Redmine.pm /usr/lib/perl5/vendor_perl/5.14.2/Apache/
    
  5. Tenemos que agregar la configuración requerida para Apache, para ello creamos y editamos posteriormente el archivo redmine_svn.conf dentro del directorio /etc/apache2/conf.d.
    testsrv:~ # touch /etc/apache2/conf.d/redmine_svn.conf
    testsrv:~ # vi /etc/apache2/conf.d/redmine_svn.conf
    
    A dicho archivo le agregamos la siguiente configuración:
    PerlLoadModule Apache::Redmine
    <location /svn>
        DAV svn
        SVNParentPath "/opt/redmine/svn"
    
        PerlAccessHandler Apache::Authn::Redmine::access_handler
        PerlAuthenHandler Apache::Authn::Redmine::authen_handler
        AuthType Basic
        AuthName "Redmine Subversion Repository"
        Require valid-user
    
        ## For mysql
        # RedmineDSN "DBI:mysql:database=databasename;host=my.db.server"
        ## For postgresql
        RedmineDSN "DBI:Pg:dbname=redmine;host=localhost"
        RedmineDbUser "redmine"
        RedmineDbPass "redmine"
    
        ## Optional where clause (fulltext search would be slow and
        ## database dependant).
        # RedmineDbWhereClause "and members.role_id IN (1,2)"
        ## Optional credentials cache size
        # RedmineCacheCredsMax 50
    </location>
    
    Finalmente reiniciamos el servicio Apache.
    testsrv:~ # service apache2 restart
    
  6. El siguiente paso consiste en dirigirnos a la pestaña Administration – Settings – Repositories en la herramienta Redmine donde habilitamos la opción WS for repository management (Habilitar SW para la gestión del repositorio), para luego generar la API key que a mi me salió ACvtc0QLUubzXJpX1Crb. Es importante aclarar que la llave API generada anteriormente será utilizada desde la línea de comandos para crear los repositorios Subversion en Redmine.


    Una vez realizado lo anterior tenemos que guardar los cambios.

  7. Para habilitar y crear el repositorio Subversion para un proyecto de Redmine primero debemos dirigirnos a la pestaña Módulos en la sección Configuración de nuestro proyecto y activar la opción Repositorio. Luego tenemos que pasar a la línea de comandos donde tenemos que ejecutar el siguiente comando para generar y activar la accesibilidad del repositorio en el proyecto deseado:
    testsrv:~ # ruby /opt/redmine/extra/svn/reposman.rb --redmine IP_SERVIDOR/redmine --scm Subversion --svn-dir /opt/redmine/svn --owner wwwrun --url file:///opt/redmine/svn --verbose --key=ACvtc0QLUubzXJpX1Crb 
    
    Es en el comando anterior donde utilizamos la llave API generada en el paso anterior. Si al acceder a las pestaña Repositorio del proyecto les llega a salir el siguiente error:
    404
    
    La entrada y/o la revisión no existe en el repositorio.
    
    Pueden probar cambiar el dueño y grupo de usuario a wwwrun www del archivo environment.rb ubicado en la carpeta config,
    testsrv:~ # chown -Rf wwwrun:www /opt/redmine/config/environment.rb
    
    reiniciando posteriormente el servicio Apache como se muestra a continuación:
    testsrv:~ # service apache2 restart
    
  8. Podemos automatizar la creación de un repositorio subversion cuando al administrador de Redmine registre un nuevo proyecto con el módulo Repositorio activado. Para ello se tiene que editar nuevamente el archivo /etc/cron.d/redmine:
    testsrv:~ # vi /etc/cron.d/redmine
    
    Al final del cual agregamos una nueva tarea programada que se encargue de realizar cada minuto la comprobación correspondiente:
    # Generacion automatica de repositorios subversion.
    * * * * * root ruby /opt/redmine/extra/svn/reposman.rb --redmine IP_SERVIDOR/redmine --scm Subversion --svn-dir /opt/redmine/svn --owner wwwrun --url file:///opt/redmine/svn --verbose --key=ACvtc0QLUubzXJpX1Crb >> /dev/null
    
    Además de la tarea anterior, agregamos otra tarea programada más que se encargará de sincronizar cada minuto los comentarios de los commits que estén referenciados a una petición/tarea.
    # Sincronización de comentarios de commits asociados a tareas.
    * * * * * root ruby /opt/redmine/script/runner "Repository.fetch_changesets" -e production > /dev/null 2>&1
    
    Finalmente reiniciamos el servicio cron.
    testsrv:~ # service cron restart
    
  9. Con los pasos anteriores ya podremos utilizar el repositorio, su integración en la herramienta quedaría como sigue:


MIGRACIÓN DE REPOSITORIOS SVN:

Para migrar un repositorio Subversion ya existente a un nuevo repositorio de Redmine podemos seguir los siguientes pasos:
  1. Generamos un dump a partir del repositorio Subversion de origen.
    testsrv:~ # svnadmin dump $PATH_REPOSITORIOS_SVN/repo_a_migrar > /tmp/archivo_export.dump
    
  2. Luego procedemos a importar el dump generado en el paso anterior en el nuevo repositorio Subversion de destino creado para nuestro proyecto de Redmine, en este caso llamado prueba:
    testsrv:~ # svnadmin load /opt/redmine/svn/prueba < /tmp/archivo_export.dump
    
  3. Por último asignamos el dueño correspondiente al repositorio de destino y ya está.
    testsrv:~ # chown -Rf wwwrun:root /opt/redmine/svn/prueba
    

ACLARACIONES SOBRE EL MÓDULO REPOSITORIO DE REDMINE:

  1. El proyecto tiene que tener activo el módulo Repositorio para que la aplicación reposman.rb pueda crear el repositorio svn físico en el directorio /opt/redmine/svn.

  2. Con la configuración anterior, si el proyecto es público se podrá realizar descargas sin autenticación del repositorio, pero para subir un cambio el usuario deberá estar registrado en el proyecto. Si el proyecto es privado, tanto para hacer el checkout como para subir algún cambio se tendrá que utilizar si o sí un usuario de la herramienta Redmine.

  3. Para que un usuario de Redmine pueda acceder al repositorio éste deberá estar agregado como miembro del proyecto. Para realizar cambios en el repositorio deberá tener el perfil Jefe de proyecto o Desarrollador, porque si tiene asignado el perfil Informador solo podrá descargar el repositorio pero no subir actualizaciones.

  4. Si se ha migrado un repositorio Subversion antiguo a un nuevo repositorio creado en Redmine, los usuarios utilizados para realizar los commits en el viejo repositorio pueden ser mapeados a los usuarios de la herramienta Redmine en la opción Usuarios de la pestaña Configuración -> Repositorio del proyecto en cuestión.


Configuración de logs

Para que Redmine guarde los registros de logs en el archivo /opt/redmine/logs/production.log se tienen que realizar las siguientes configuraciones:
  1. Primero dirigirnos al directorio /opt/redmine/config y crear el archivo additional_environment.rb a partir de su archivo plantilla:
    testsrv:~ # cd /opt/redmine/config/
    testsrv:/opt/redmine/config # cp additional_environment.rb.example additional_environment.rb
    
  2. Luego editamos el archivo additional_environment.rb,
    testsrv:/opt/redmine/config # vi additional_environment.rb
    
    y al final del mismo le agregamos la siguiente configuración:
    #Logger.new(PATH,NUM_FILES_TO_ROTATE,FILE_SIZE)
    config.logger = Logger.new(config.log_path, 2, 1000000)
    config.logger.level = Logger::INFO
    
  3. Para que los cambios tomen efecto reiniciamos el servicio Apache.
    testsrv:~ # service apache2 restart
    


Actualización de temas (themes)

Podemos agregar nuevos themes para personalizar el look & feel de la herramienta, los pasos para agregarlos van a continuación.
  1. Lo primero es descargar el nuevo tema deseado desde el sitio web que sigue a continuación:
    URL: http://www.redmine.org/projects/redmine/wiki/Theme_List
    
  2. Luego lo tenemos que copiar y descomprimir en la carpeta /opt/redmine/public/themes.
    testsrv:/opt/redmine/public/themes # tar -xzf a1-1_0_2.tar.gz
    
  3. Y finalmente le asignamos los mismos permisos de los demás temas.
    testsrv:/opt/redmine/public/themes # chown -Rf root:root a1
    
  4. Con eso ya está, ya podremos seleccionar el nuevo tema reciéntemente agregado en la pestaña Mostrar (Show) de la sección de Administración de la herramienta (http://server_ip_or_domain/redmine/settings), y si tenemos el plugin Theme Changer directamente desde la página del perfil de cada usuario. De mi parte les recomiendo probar los siguientes themes disponibles:


Realización de copias de seguridad

Debido a que la información que se almacena en Redmine es de mucho valor, he decido agregar a esta guía el método necesario para realizar una copia de seguridad completa de la herramienta.
  1. En principio necesitamos definir un directorio en donde ubicar las copias de seguridad realizadas, en mi caso voy a crear una carpeta llamada backups en el directorio raíz.
    testsrv:~ # mkdir /backups
    
  2. Luego pasamos a crear los directorios backups y backups/svndumps dentro de /opt/redmine para almacenar las copias de seguridad en bruto de la base de datos y de los repositorios subversion que tenemos agregados:
    testsrv:~ # mkdir -p /opt/redmine/backups/svndumps
    
  3. A continuación accedemos al directorio /opt/redmine/script y creamos el archivo backup que contendrá el script que realizará la copia de seguridad, además aprovechamos la ocasión para asignarle los permisos correspondientes:
    testsrv:~ # cd /opt/redmine/script/
    testsrv:/opt/redmine/script # touch backup
    testsrv:/opt/redmine/script # chmod 750 backup
    
  4. Luego editamos el archivo backup,
    testsrv:/opt/redmine/script # vi backup
    
    y le agregamos el siguiente script bash:
    #!/bin/bash
    # Realiza una copia de seguridad completa de la herramienta Redmine.
    DIA=`date +"%Y%m%d"`
    HORA=`date +"%H%M"`
    BACKUP_PATH=/backups
     
    # -- REDMINE
    REDMINE_HOME=/opt/redmine
    REDMINE_DB_TYPE=pg #[pg|mysql]
    REDMINE_DB_NAME=redmine
    REDMINE_DB_USER=redmine
    REDMINE_DB_PASS=redmine
    REDMINE_DB_BACKUP=$REDMINE_HOME/backups/redmine_db.sql
    REDMINE_BACKUP_NAME="redmine_"$DIA"_"$HORA".tar.gz"
    REDMINE_BACKUP_HISTO="histo_redmine_"$DIA"_"$HORA".tar.gz"
    REDMINE_BACKUP_LIVE_TIME=30
    REDMINE_BACKUP_HISTO_LIVE_TIME=365
     
    # -- SVN
    SVN_REPOS_PATH=$REDMINE_HOME/svn
    SVN_BACKUP_PATH=$REDMINE_HOME/backups/svndumps
     
    # -- PATRON LIMPIEZA
    PATRON_BKP_DIARIO=redmine_*.tar.gz
    PATRON_BKP_HISTO=histo_redmine_*.tar.gz
     
    # -- FTP
    FTP_SERVER=ip_servidor_backup_ftp
    FTP_USER=usuario_ftp
    FTP_PASS=password_ftp
    FTP_REMOTE_CD=remote_backups
    FTP_LOCAL_CD=$BACKUP_PATH
     
    # Backup de Proyectos SVN
    echo
    echo "-->BACKUP DE REPOSITORIOS SVN"
    echo "===================================================================="
    cd $SVN_REPOS_PATH
    for SVN_REPO_NAME in *
    do
        echo "---------- Iniciando exportacion del repositorio '$SVN_REPO_NAME' ----------"
        /usr/bin/svnadmin dump $SVN_REPOS_PATH/$SVN_REPO_NAME > $SVN_BACKUP_PATH/$SVN_REPO_NAME.dump
        echo "------------- Fin exportacion del repositorio '$SVN_REPO_NAME' -------------"
        echo
    done
     
    # Segun el motor de base de datos especificado se procede a exportar la base de datos de Redmine.
    echo
    echo "-->BACKUP DE LA BASE DE DATOS DE REDMINE"
    echo "===================================================================="
    if [ $REDMINE_DB_TYPE == "mysql" ]; then
        echo "Exportando la base de datos de Redmine a partir de MySQL. Aguarde un momento..."
        mysqldump -v -u $REDMINE_DB_USER -p$REDMINE_DB_PASS --database $REDMINE_DB_NAME > $REDMINE_DB_BACKUP
        echo "Fin del proceso de exportacion."
        echo
    elif [ $REDMINE_DB_TYPE == "pg" ]; then
        echo "Exportando la base de datos de Redmine a partir de PostgreSQL. Aguarde un momento..."
        export PGUSER=$REDMINE_DB_USER
        export PGPASSWORD=$REDMINE_DB_PASS
        pg_dump -b -F p --column-inserts $REDMINE_DB_NAME > $REDMINE_DB_BACKUP
        unset PGUSER
        unset PGPASSWORD
        echo "Fin del proceso de exportacion."
    fi
     
    # Se generan los archivos con todas las copias de seguridad para ser enviadas a una unidad de cinta.
    echo
    echo "-->CREANDO FULL BACKUP DE REDMINE"
    echo "===================================================================="
    tar -czf $BACKUP_PATH/$REDMINE_BACKUP_NAME $REDMINE_HOME
     
    # Almacenando una copia de seguridad alternativa si la fecha corresponde a fin de mes.
    TOMORROW=`date --date=tomorrow +%d`
    if [ $TOMORROW -eq "1" ]; then
        echo
        echo "-->CREANDO BACKUP HISTORICO POR SER FIN DE MES"
        echo "===================================================================="
        cp $BACKUP_PATH/$REDMINE_BACKUP_NAME $BACKUP_PATH/$REDMINE_BACKUP_HISTO
    fi
     
    # Para no llenar el disco duro con backups, se eliminan todos los backups diarios pasados la cantidad
    # de dias especificados en la variable REDMINE_BACKUP_LIVE_TIME, lo backups historicos se eliminan luego 
    # de la cantidad de dias expecificados en la variable REDMINE_BACKUP_HISTO_LIVE_TIME.
    echo
    echo "-->LIMPIEZA DE BACKUPS ANTIGUOS"
    echo "===================================================================="
    find $BACKUP_PATH/$PATRON_BKP_DIARIO -mtime +$REDMINE_BACKUP_LIVE_TIME -exec rm {} \;
    find $BACKUP_PATH/$PATRON_BKP_HISTO -mtime +$REDMINE_BACKUP_HISTO_LIVE_TIME -exec rm {} \;
     
    # Se copia el full backup a un servidor de respaldo.
    echo
    echo "-->COPIANDO EL FULL BACKUP DE REDMINE A UN SERVIDOR DE RESPALDO"
    echo "===================================================================="
    /usr/bin/ftp -n <<EOD
        open $FTP_SERVER
        quote USER $FTP_USER
        quote PASS $FTP_PASS
        bin
        cd $FTP_REMOTE_CD
        lcd $FTP_LOCAL_CD
        put $REDMINE_BACKUP_NAME
        bye
    EOD
    
    Enlace: Script en Github Gist.

    Este script se encarga de realizar una copia de seguridad de la base de datos de la herramienta y de los repositorios subversion agregados. Genera copias de seguridad periódicas y mensuales compresas en tar.gz de todo el directorio /opt/redmine, elimina las copias de seguridad muy antiguas y transfiere la última copia de seguridad a un equipo remoto mediante ftp.

  5. Para programar la ejecución periódica del script debemos agregar una tarea programada. Para ello editamos nuevamente el archivo /etc/cron.d/redmine:
    testsrv:~ # vi /etc/cron.d/redmine
    
    Para luego agregarle al final del mismo el siguiente contenido:
    # Backup Redmine
    30 22 * * * root /opt/redmine/script/backup >> /dev/null
    
    Finalmente reiniciamos el servicio cron para que la tarea programada sea funcional.
    testsrv:~ # service cron restart
    

Plugins interesantes

A continuación va una lista de plugins que a mi parecer agregan funcionalidades muy interesantes y necesarias a la herramienta Redmine. Para su instalación les recomiendo siempre seguir las instrucciones definidas por los autores de cada plugin.
OBS: Los plugins siempre deben ser probados en una instalación de prueba, nunca en el servidor de producción, ya que algunos suelen fallar dependiendo de la versión de Redmine, Ruby, etc.
Los plugins recomendados son los siguientes:

Otras capturas de pantalla

Información técnica

  • openSUSE 12.1
  • Apache 2.2
  • Ruby 1.8.7
  • Redmine 1.3.0
  • Perl 5.14.2

Fuentes

Enlaces externos

Comentarios

  1. Excelente el artículo, muchas gracias.
    Necesito ayuda, no pude hacerlo andar completamente.

    ingreso a http://localhost/redmine y me arroja el siguiente error:

    "Ruby on Rails application could not be started
    Error message:
    /srv/redmine/Gemfile not found (Bundler::GemfileNotFound)
    Exception class:
    PhusionPassenger::UnknownError
    Application root:
    /srv/redmine "

    Sin embargo, si ejecuto el siguiente comando:

    ruby script/rails server webrick -e production

    funciona, pero en la direccion http://localhost:3000

    El comando RAILS_ENV=production rake db:migrate funciono, me creo todas las tablas en la base de datos (PostgreSQL).

    Tengo openSuse 12.2
    ya probe permisos, pero no logro encontrar la solucion.

    Muchas Gracias !!!

    ResponderEliminar
    Respuestas
    1. Hola Tincho, si funciona con webrick supongo que el problema debe estar en el módulo Passenger para Apache.

      Deberías fijarte si Apache lo carga correctamente, también podrías controlar que los path's especificados en el archivo de configuración del módulo Passenger sean los correctos y que realmente apunten a un directorio real en el sistema operativo.

      Atte...

      Eliminar
  2. Eso es porque en alguna parte se salto un comando que hay que poner...
    ademas lo dice clarito el error..... Bundler::GemfileNotFound

    gem install bundle

    bundle install

    esto se hace en la raiz. almenos eso se hace en centos.

    pero el manual esta muy bueno, lo he ocupado para corregir algunos errores que tenia.

    yo seguí este manual.

    http://www.redmine.org/projects/redmine/wiki/how_to_install_redmine_on_centos_(detailed)

    ResponderEliminar
    Respuestas
    1. Hola, gracias por comentar, realmente le faltaba el paquete bundle pero lo raro es que no haya instalado y configurado antes el módulo passenger como lo indica la guía. Saludos!

      Eliminar
  3. Hola!
    Estoy queriendo integrar un SVN ha está siendo utilizado independientemente del redmine, con un repositorio redmine. En este caso, con un link simbolico ya alcanzaria?

    ResponderEliminar
    Respuestas
    1. Hola, la verdad que no lo he probado, yo lo que hice fue exportar el anterior repo y volver a importarlo dentro del nuevo repositorio svn de Redmine, que es la opción que más me gustó.

      Enlazado simbólicamente no se si funcionaría el mapeado de usuario, la integración entre las tareas de Redmine y los comentarios de los commits, supongo que la base de datos de usuarios de Redmine y del repositorio seguirían siendo distintos, en fin, es cuestión de probar. Saludos!

      Eliminar
  4. Hola mi duda es como ligar las etiquetas personalizables a la base de datos para que al teclear el contenido en una etiqueta, llene automaticamente el de la siguiente ejemplo:
    Tecleo un id de articulo que esta en una tabla y lo que debe mostrar en la siguiente etiqueta es el nombre del articulo, no se si me explico? Si alguien me puede ayudar mil gracias de antemano!!!

    ResponderEliminar

Publicar un comentario

Entradas populares