Cómo publicar rápidamente en tu PPA de Ubuntu

Esta entrada es, principalmente, unas cuantas notas personales con instrucciones para publicar rápidamente un paquete (habitualmente parcheado) en mis propios PPAs.

Parcheando un paquete existente

Lo primero es descargar las fuentes del paquete del repositorio que está proporcionando la versión que queremos parchear y cuyo binario tenemos instalado en el sistema.

Por ejemplo, para parchear webkitgtk, si el paquete que está instalado procede directamente de Ubuntu, sólo tendremos que comprobar que tenemos el repositorio de fuentes oficial de Ubuntu. Sin embargo, si el paquete procede de otro PPA, tendremos que comprobar que también tenemos el repositorio con las fuentes de ese mismo PPA. De no ser así, tendremos que descargar los ficheros necesarios de forma manual. Asumamos que el paquete que tenemos instalado procede del PPA del GNOME3 Team:

$ cd ~/ppa/ && mkdir -p webkitgtk/gnome3 && cd webkitgtk/gnome3
$ apt-get source webkitgtk
Reading package lists... Done
Building dependency tree
Reading state information... Done
NOTICE: 'webkitgtk' packaging is maintained in the 'Git' version control system at:
git://git.debian.org/git/pkg-webkit/webkit.git
Need to get 9,440 kB of source archives.
Get:1 http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu/ saucy/main webkitgtk 2.3.2-1ubuntu6~saucy1 (tar) [9,353 kB]
Get:2 http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu/ saucy/main webkitgtk 2.3.2-1ubuntu6~saucy1 (diff) [82.2 kB]
Get:3 http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu/ saucy/main webkitgtk 2.3.2-1ubuntu6~saucy1 (dsc) [4,577 B]
Fetched 9,440 kB in 3s (2,769 kB/s)
gpgv: Signature made Sun 22 Dec 2013 01:34:25 AM EET using RSA key ID 153ACABA
gpgv: Can't check signature: public key not found
dpkg-source: warning: failed to verify signature on ./webkitgtk_2.3.2-1ubuntu6~saucy1.dsc
dpkg-source: info: extracting webkitgtk in webkitgtk-2.3.2
dpkg-source: info: unpacking webkitgtk_2.3.2.orig.tar.xz
dpkg-source: info: unpacking webkitgtk_2.3.2-1ubuntu6~saucy1.debian.tar.gz
dpkg-source: info: applying 02_notebook_scroll.patch
dpkg-source: info: applying aarch64.patch
dpkg-source: info: applying fix-ppc.diff
dpkg-source: info: applying fix-aarch64.patch
dpkg-source: info: applying remove-use-lockfree-threadsaferefcounted.patch
dpkg-source: info: applying no-jit-build-failure.patch
dpkg-source: info: applying 0001-GTK-Fails-to-build-with-freetype-2.5.1.patch
dpkg-source: info: applying disable-jit-harder.patch
dpkg-source: info: applying fix-llint-c-loop.patch
dpkg-source: info: applying fix-armv7.patch
dpkg-source: info: applying bugzilla_clear_surface.patch
dpkg-source: info: applying ppc64el.patch
$ cd webkitgtk-2.3.2

Por si acaso, algo que me gusta hacer es añadir el código descargado a un sistema de control de versiones local con git:

$ git init
$ git add *
$ git commit -m "Initial commit"
...

Ahora es el momento de realizar los cambios al código fuente. Esta es mi principal razón por la que git puede resultarnos útil si es que los cambios no son triviales y necesitamos realizar algo de trabajo para tener una versión funcional. Una vez que hemos finalizado los cambios debemos añadirlos al paquete debian como un parche adicional al código fuente original. Esto lo haremos con dpkg-source:

$ dpkg-source --commit
dpkg-source: info: local changes detected, the modified files are:
 webkitgtk-2.3.2/Source/WebKit2/GNUmakefile.am
 webkitgtk-2.3.2/Source/WebKit2/GNUmakefile.list.am
 webkitgtk-2.3.2/Source/WebKit2/Shared/Plugins/Netscape/NetscapePluginModule.h
 webkitgtk-2.3.2/Source/WebKit2/Shared/Plugins/Netscape/x11/NetscapePluginModuleX11.cpp
 webkitgtk-2.3.2/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.cpp
 webkitgtk-2.3.2/Source/WebKit2/UIProcess/Plugins/gtk/PluginInfoCache.h
 webkitgtk-2.3.2/Source/WebKit2/UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp
Enter the desired patch name: 0001-GTK-WK2-Blocks-when-fetching-plugins-information.patch
...

Escribimos el nombre del parche y la descripción de los cambios realizados:

$ cat debian/patches/0001-GTK-WK2-Blocks-when-fetching-plugins-information.patch
Description: [GTK][WK2] Blocks when fetching plugins information
 https://bugs.webkit.org/show_bug.cgi?id=115650
 .
 Patch by Carlos Garcia Campos.
 Reviewed by Gustavo Noronha Silva.
 .
 Use a persistent cache to store the plugins metadata to avoid
 having to load all the plugins everytime a plugin is used for the
 first time.
 .
 * GNUmakefile.am:
 * GNUmakefile.list.am:
 * Shared/Plugins/Netscape/NetscapePluginModule.h:
 * Shared/Plugins/Netscape/x11/NetscapePluginModuleX11.cpp:
 (WebKit::NetscapePluginModule::parseMIMEDescription): Make this
 method public.
 (WebKit::NetscapePluginModule::buildMIMEDescription): Added this
 helper to build the MIME description string.
 * UIProcess/Plugins/gtk/PluginInfoCache.cpp: Added.
 (WebKit::PluginInfoCache::shared):
 (WebKit::PluginInfoCache::PluginInfoCache):
 (WebKit::PluginInfoCache::~PluginInfoCache):
 (WebKit::PluginInfoCache::saveToFileIdleCallback):
 (WebKit::PluginInfoCache::saveToFile):
 (WebKit::PluginInfoCache::getPluginInfo):
 (WebKit::PluginInfoCache::updatePluginInfo):
 * UIProcess/Plugins/gtk/PluginInfoCache.h: Added.
 * UIProcess/Plugins/unix/PluginInfoStoreUnix.cpp:
 (WebKit::PluginInfoStore::getPluginInfo): Check first if we have
 metadata of the plugin in the cache and update the cache if we
 loaded the plugin to get its metadata.
...

Finalmente, modificaremos la información de publicación añadiendo o incrementando el digito «non-maintainer». Por ejemplo, para este caso la versión del código descargado es 2.3.2-1ubuntu6~saucy1 por lo que modificaremos la versión a 2.3.2-1ubuntu6~saucy1.1. Debemos también acordarnos de proporcionar el nombre adecuado de distribución o bien modificarlo al adecuado cuando estemos introduciendo el resumen de los cambios realizados. En este caso la distribución sería saucy. Comprueba también que estás utilizando la dirección de correo electrónico adecuada en el resumen de los cambios. En el caso de mis PPAs, uso mi cuenta personal:

$ DEBEMAIL="mi@cuenta-de.correo" dch -n -D saucy
$ cat debian/changelog
webkitgtk (2.3.2-1ubuntu6~saucy1.1) saucy; urgency=low

  * Fixes #115650:
    - debian/patches/0001-GTK-WK2-Blocks-when-fetching-plugins-information.patch

 -- Andres Gomez   Wed, 19 Mar 2014 14:26:19 +0200
...

Con esto habremos terminado de modificar el código fuente del paquete.

Alternativa mediante la importación de un parche

Quizá esta es la forma más limpia y rápida de parchear el código fuente del paquete descargado. En vez de modificar el código y ejecutar dpkg-source –commit, símplemente podemos importar un parch ya existente que se pueda aplicar sin problemas sobre el código fuente.

Para ello ejecutaremos:

$ quilt import //mi_parche.patch

Este método es también válido para versiones de paquetes Debian en los que no funciona el comando dpkg-source –commit. Además, es la forma más rápida de reutilizar un parche para un paquete de una versión previa de Ubuntu en una nueva versión, por ejemplo.

A partir de este punto retomaremos los mismos pasos que se describieron anteriormente para añadir la información de publicación.

Construyendo el paquete con el código fuente

Sólo tenemos que tener en cuenta que, si tenemos más de una clave GPG, el firmado del paquete fallará, tal y como muestra la siguiente línea:

$ debuild -S -rfakeroot
...
Finished running lintian.
Now signing changes and any dsc files...
 signfile webkitgtk_2.3.2-1ubuntu6~saucy1.1.dsc Andres Gomez 
gpg: skipped "Andres Gomez ": secret key not available
gpg: /tmp/debsign.vhpVY32w/webkitgtk_2.3.2-1ubuntu6~saucy1.1.dsc: clearsign failed: secret key not available
debsign: gpg error occurred!  Aborting....
debuild: fatal error at line 1280:
running debsign failed

Debido a esto, tenemos que especificar el id de la clave a usar mediante el parámetro -k.

Además, si el código fuente del paquete no procede de uno de los repositorios oficiales de Ubuntu, tendremos que proporcionar el código fuente original para que también sea transferido al PPA. Esto lo haremos pasando el parámetro -sa. En nuestro ejemplo, como el código fuente proced del PPA del GNOME3 Team, el comando sería algo como:

$ debuild -S -sa -rfakeroot -k3FEA1034

Mientras que para otros paquetes que hayamos modificado a partir de fuentes que procedan directamente de uno de los repositorios oficiales de Ubuntu, usaremos:

$ debuild -S -rfakeroot -k3FEA1034

Construcción local opcional

Construir el paquete localmente no es un paso realmente necesario pero nos dirá si los cambios realizados están «rompiendo» la compilación.

La mejor manera de hacer esto de una manera confiable es mediante pbuilder.

Cuando usemos pbuilder nos tendremos que asegurar de que estamos usando los paquetes adecuados, no sólo los que proceden de los repositorios oficiales de Ubuntu, si no también que estamos usando los que proporcionan los PPAs de los cuales depende nuestro PPA y también los proporcionados por nuestro propio PPA.

Yo ya me he creado los ficheros comprimidos con los «chroot» necesarios con las distribuciones adecuadas para mis PPAs. Sin embargo, con el ánimo de mostrar un ejemplo, usaríamos un comando parecido al que sigue para crear este fichero comprimido si mi PPA objetivo fuese gnome3, que depende de mi otro PPA ppa y también del PPA gnome3 del GNOME3 Team:

$ sudo pbuilder --create --distribution saucy --mirror "http://fi.archive.ubuntu.com/ubuntu/" --othermirror "deb http://fi.archive.ubuntu.com/ubuntu/ saucy restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-updates main restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-proposed main restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-security main restricted universe multiverse|deb http://archive.canonical.com/ubuntu saucy partner|deb http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu trusty main|deb http://ppa.launchpad.net/tanty/ppa/ubuntu saucy main|deb http://ppa.launchpad.net/tanty/gnome3/ubuntu saucy main" --basetgz //saucy-gnome3.tgz --buildplace //build --aptcache  //aptcache/

Utilizo <ruta_base_de_pbuilder> porque, por defecto, todo el proceso de la creación del fichero comprimido se realiza en /var y no siempre tengo el espacio necesario allí.

Una vez que el fichero comprimido ha sido creado y siguiendo nuestro ejemplo, construiríamos el paquete para el PPA objetivo gnome3 tal y como sigue:

$ sudo pbuilder --build --mirror "http://fi.archive.ubuntu.com/ubuntu/" --othermirror "deb http://fi.archive.ubuntu.com/ubuntu/ saucy main restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-updates main restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-proposed main restricted universe multiverse|deb http://fi.archive.ubuntu.com/ubuntu/ saucy-security main restricted universe multiverse|deb http://archive.canonical.com/ubuntu saucy partner|deb http://ppa.launchpad.net/gnome3-team/gnome3/ubuntu trusty main|deb http://ppa.launchpad.net/tanty/ppa/ubuntu saucy main|deb http://ppa.launchpad.net/tanty/gnome3/ubuntu saucy main" --basetgz //saucy-gnome3.tgz --buildplace //build --aptcache  //aptcache/ ../webkitgtk_2.3.2-1ubuntu6~saucy1.1.dsc

Ya sólo resta esperar y comprobar los resultados.

Publicando en el PPA

El último paso es transferir el paquete con los cambios a nuestro PPA.

En mi caso, tengo un PPA para pruebas por cada PPA estable. Estos PPAs no están pensados para su utilización por el usuario de Ubuntu general sino, simplemente, para poder jugar con los cambios que realizo hasta que siento que son lo suficientemente estables como para ser publicados en mis PPAs estables. Por esto, los 4 PPAs que manejo son:

  • ppa: Donde publico los paquetes procedentes de repositorios oficiales de Ubuntu con cambios que me son útiles.
  • ppa-next: No dirigido al público general. Aquí tengo los paquetes inestables hasta que son suficientemente estables como para ser publicados en el PPA ppa.
  • gnome3: Donde publico los paquetes procedentes del PPA del GNOME3 Team con cambios que me son útiles.
  • gnome3-next: No dirigido al público general. Aquí tengo los paquetes inestables hasta que son suficientemente estables como para ser publicados en el PPA gnome3.

Durante el primer ciclo de desarrollo publico los cambios en mis PPAs inestables antes de publicarlos en los estables. Siguiendo nuestro ejemplo, el PPA en el que publicaría por primera vez sería gnome3-next:

$ dput ppa:tanty/gnome3-next ../webkitgtk_2.3.2-1ubuntu6~saucy1.1_source.changes

Cuando ya estoy lo suficientemente convencido de mis cambios, lo siguiente sería publicar en el PPA estable:

$ dput -f ppa:tanty/gnome3 ../webkitgtk_2.3.2-1ubuntu6~saucy1.1_source.changes

El argumento -f lo utilizo para evitar el error que se produce cuando ya existe un fichero de «log» procedente de una publicación anterior de un fichero «.changes» mediante dput.

Tras esto, sólo tenemos que esperar a que el paquete sea contruído en los bots del PPA, actualizar nuestros repositorios y actualizar el sistema:

$ sudo apt-get update && sudo apt-get upgrade

Disfruta tu nuevo paquete!

4 comentarios en “Cómo publicar rápidamente en tu PPA de Ubuntu

  1. Another alternative is git-buildpackage. Basically it takes your debian sources and creates a repository with everything there. Afterwards, you can do the changes and commit there.

    Great stuff about it is that it creates an ‘upstream’ branch that contains the upstream code, without the debian files. And also it is in charge of creating the patches to put in the debian/patches automatically.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *