Como publicar seu software no Copr, o Repositório de Usuários do Fedora

Isso é um breve tutorial em como criar e manter um repositório Copr para seu software de forma automatizada. Será presumido alguma familiaridade básica com Git e como criar um pacote RPM.

Neste guia, nós vamos

  • criar um pacote RPM para um programa

  • criar um repositório Copr e publicar o programa no mesmo

  • configurar o gerenciamento automático da versão do programa, seu lançamento e das notas de atualização do pacote

  • configurar a construção automática de novas versões do pacote

O objetivo é lhe permitir manter seu software atualizado no Copr sem precisar interagir com nada além do repositório Git do seu programa.

Você pode configurar uma automação similar quando empacotar o programa de outra pessoa, ou seja, construir o programa a partir de uma tarball fonte baixada. As modificações necessárias são descritas no fim do tutorial.

Pré-requisitos

O seguinte é necessário:

  1. A fonte de nosso programa precisa estar disponível publicamente em um repositório git em algum lugar. Esse tutorial usa um programa executável simples- hellocopr - para demonstrar o processo. O programa e todos os arquivos referenciados nesse guia podem ser encontrados no repositório git do projeto. É um programa em Python muito simples (e inútil) com um instalador via setuptools:

    user@host ~/copr-tito-quickdoc % ls src/hellocopr colors.py hellocopr.py __init__.py ```
    +
    . Uma conta do Fedora (FAS) é necessária para criar repositórios no Copr. O repositório de demonstração desse tutorial pode ser encontrado link:https://copr.fedorainfracloud.org/coprs/lcts/hellocopr/[aqui].
    
    . `tito` deve estar instalado no seu sistema. link:https://github.com/rpm-software-management/tito[Tito] é capaz de automações avançadas para criação de pacotes, a grande maioria dos quais nós não precisaremos aqui. Confira a sua documentação para aprender mais.
    
    . Um arquivo spec para nosso programa também é necessário. Para mais informações sobre como criar um, confira o xref:package-maintainers::Packaging_Tutorial_GNU_Hello.adoc[Tutorial de Empacotamento: GNU Hello] ou adapte o link:https://pagure.io/copr-tito-quickdoc/blob/master/f/doc/hellocopr.spec.annotated[arquivo spec anotado de exemplo] desse tutorial.
    
    TIP: Você pode seguir esse tutorial clonando ou fazendo um fork do repositório e conferindo a tag `initial`. Isso colocará o repositório neste estado logo antes do próximo passo. O histórico de commits do repositório deve ser igual aos passos seguidos nesse tutorial.
    
    == Primeiro passo: Criando o pacote usando o tito
    
    Copie link:https://pagure.io/copr-tito-quickdoc/c/00963ac9339a13eefd2ab1ca42b1f72af12d3cac?branch=master[o arquivo spec] no diretório base do projeto. Algumas mudanças devem ser feitas antes de prosseguir:
    
    . Os valores de `Version:` e `Release:` não importam, já que esses serão gerenciados pelo tito. Faz sentido definí-los como `Version: 0.0.0` e `Release: 0%\{?dist}` para marcar que esse pacote ainda não foi construído.
    
    . tito também lidará com a criação da tarball fonte vinda do repositório git, então mude a URL `Source0: ` para o nome do arquivo `%\{name}-%\{version}.tar.gz` e adicione um comentário para dizer aos usuários como baixar a tarball
    
    . As notas de atualização também podem ficar vazias.
    +
    ``` user@host ~/copr-tito-quickdoc % cat hellocopr.spec ... Version: 0.0.0 Release: 0%\{?dist} ... # Fontes podem ser obtidas com # git clone https://pagure.io/copr-tito-quickdoc # cd copr-tito-quickdoc # tito build --tgz Source0: %\{name}-%\{version}.tar.gz ... %changelog ```
    
    Faça um commit das mudanças.
    
    A seguir, vamos inicializar o projeto para seu uso com o tito.
    
    ``` user@host ~/copr-tito-quickdoc % tito init Creating tito metadata in: ~/copr-tito-quickdoc/.tito
       - created ~/copr-tito-quickdoc/.tito
       - wrote tito.props
       - created ~/copr-tito-quickdoc/.tito/packages
       - wrote ~/copr-tito-quickdoc/.tito/packages/.readme
    committed to git Done! ```
    
    Isso cria link:https://pagure.io/copr-tito-quickdoc/c/7a6919d3dd56943bb988a755f8233157965aa9bb?branch=master[um subdiretório `.tito` com algumas configurações padrão], que pode ser deixado como está por agora.
    
    Podemos agora fazer uma build de testes do pacote usando `tito build`. Geralmente o tito construirá a partir de uma tag, que nós ainda não criamos. Apesar disso, usando a flag `--test`, podemos ao invés disso construir a partir do commit mais recente , que será gravada em `/tmp/tito`:
    
    ``` user@host ~/copr-tito-quickdoc % tito build --rpm --test Creating output directory: /tmp/tito WARNING: unable to lookup latest package tag, building untagged test project WARNING: .tito/packages/hellocopr doesn't exist in git, using current directory Building package [hellocopr-0.0.0-0] Wrote: /tmp/tito/hellocopr-git-11.7a6919d.tar.gz ...
    
    Successfully built: /tmp/tito/hellocopr-0.0.0-0.git.11.7a6919d.fc32.src.rpm
    /tmp/tito/noarch/hellocopr-0.0.0-0.git.11.7a6919d.fc32.noarch.rpm ```
    
    Uma vez que consertamos quaisquer problemas com o pacote que possam aparecer, podemos deixar o tito criar um lançamento de pacote usando `tito tag`. Já que ainda não criamos uma versão de verdade, precisamos passar isso para o tito ao criar a primeira tag:
    
    ``` user@host ~/copr-tito-quickdoc % tito tag --use-version 1.0.0 ```
    
    Isso abrirá o editor e mostrar uma nota de atualização pré-formatada construída com todos os commits desde o último lançamento, que podemos editar como for necessária. Já que não houve nenhum até agora, a nota vai conter apenas "- novo pacote construído com tito". Salve o arquivo, link:https://pagure.io/copr-tito-quickdoc/c/f44e81d695df669bcdb7237612baf41b80da98e0?branch=master[e o tito vai]
    
    . definir a versão (Version) do arquivo spec para 1.0.0
    
    . definir o lançamento (Release) no arquivo spec para 1
    
    . adicionar as notas de atualização na seção `%changelog` do arquivo spec
    
    . fazer um commit do resultado e adicionar uma tag ao mesmo com `<nome>-<versão>-<release>, nesse caso `hellocopr-1.0.0-1`
    +

    user@host ~/copr-tito-quickdoc % tito tag --use-version 1.0.0 Creating output directory: /tmp/tito Tagging new version of hellocopr: untagged → 1.0.0-1 Created tag: hellocopr-1.0.0-1 View: git show HEAD Undo: tito tag -u Push: git push --follow-tags origin

Faça um push dos commits e tags para o remoto usando `git push --follow-tags`, e com isso estamos prontos para lançar o pacote no Copr.

== Segundo passo: Publicando o pacote em um repositório Copr

. Vá para https://copr.fedorainfracloud.org/ e faça login. Uma vez que esteja logado, clique em _New Project_ (Novo Projeto) e comece a criar um repositório para nosso programa. Nas entradas de input a seguir,

.. Em _1. Project information_ (Informações do projeto) -> _Project name_ (Nome do projeto) defina o nome de como você quer que seu repositório se chame - já que ele conterá apenas um único pacote, faz sentido usar nomedoprojeto = nomedopacote, nesse caso _hellocopr_. Essa é a única configuração que não pode ser modificada depois.

.. Em _2. Build options_ (Opções de build) marque todas as distribuições para as quais você deseja criar repositórios - geralmente todas as versões do Fedora e talvez versões para o EPEL também

.. Em _4. Other Options_ (Outras Opções) garanta que _Follow Fedora branching_ (Seguir ramificação do Fedora) está marcada, isso garantirá que seu repositório será automaticamente atualizado para cada novo lançamento do Fedora.

. Vá para _Packages_ (Pacotes) -> _New Package_ (Novo Pacote)

.. Em _1. Provide the source_ (Adicione a fonte), defina o nome do pacote e a URL do seu repositório git

.. Em _2. How to build SRPM from the source_ (Como construir o SRPM a partir da fonte) selecione _tito_

.. Em _3. Generic package setup_ (Configurações genéricas do pacote) marque a opção de _Auto-rebuild_ (Reconstrução automática)

. Seu pacote aparecerá na lista de pacotes. Selecione _Rebuild_ para iniciar uma construção. A página a seguir lhe permite mudar quaisquer opções de build se necessário, mas iremos utilizar apenas os padrões, ou seja, as opções que configuramos no último passo. Clique em _Submit_ (Confirmar) e o Copr construirá o pacote a partir da tag do tito que criamos no Primeiro passo.

Uma vez que a construção estiver finalizada, você pode experimentar instalar o pacote através do Copr ativando seu repositório. ``` user@host ~/copr-tito-quickdoc % sudo dnf copr enable <username>/hellocopr

user@host ~/copr-tito-quickdoc % sudo dnf install hellocopr ```

== Terceiro passo: Automatizando a (re)construção do pacote

Em seguida, vamos configurar o Copr para construir automaticamente uma nova versão do pacote quando criarmos uma, para que não precisemos fazer login e iniciar uma manualmente. Para fazer isso, precisamos simplesmente iniciar uma construção quando fizermos push de uma nova tag para o repositório.

Isso requer uma certa configuração tanto do seu repositório Git e do seu projeto Copr.

A configuração no Copr pode ser encontrada em _Settings_ (Configurações) -> _Integrations_ (Integrações), a página também explica os passos para configurar seu repositório git para todas as _forges_ Git mais comuns (Pagure, GitHub, GitLab e BitBucket).

Agora, para testarmos, vamos fazer algumas mudanças no nosso programa que virão a calhar para a última camada de automação e criar uma nova atualização para nosso software.

Atualmente o programa de exemplo tem sua versão manualmente definida em inúmeros lugares. link:https://pagure.io/copr-tito-quickdoc/c/61abf1cdf622d8c9fb4f03eb6b06c4ddc1677362?branch=master[Vamos mudar isso] para que a string de versão seja modificada por um único arquivo. Não importa que arquivo seja, mas idealmente a variável de versão deve ser a única coisa que provavelmente mudará. Nesse caso, vamos usar o arquivo `src/hellocopr/pass:[__]initpass:[__].py` que anteriormente estava vazio. Vamos nomear essa nova versão '1.0.1'.

Faça um commit das mudanças, e crie um novo lançamento com tito

user@host ~/copr-tito-quickdoc % tito tag Creating output directory: /tmp/tito Tagging new version of hellocopr: 1.0.0-1 → 1.0.1-1 Created tag: hellocopr-1.0.1-1 View: git show HEAD Undo: tito tag -u Push: git push --follow-tags origin

Note que ao omitir a opção `--use-version`, tito agora atualiza a versão automaticamente. Ele o faz

. Aumentando o dígito final da versão em 1 - `1.0.0` -> `1.0.1`
. Resetando o lançamento para 1 se já não foi feito antes.

Se você quiser aumentar para uma versão diferente, por exemplo `1.1.0`, você pode fazê-lo passando novamente `--use-version`.

Faça push do commit e da tag resultantes, e se você conferir a página do seu projeto no Copr, você verá que uma nova build do `hellocopr-1.0.1-1` foi iniciada por termos feito push da tag.

== Quarto passo: Deixar o tito gerenciar a versão do programa

Se você chegar o log do git, você vai descobrir que eu na verdade esqueci de atualizar a variável de versão do hellocopr para 1.0.1. Não queremos que isso aconteça novamente. Por sorte, já que fizemos o processo de modificação da versão para uma única fonte, podemos deixar o tito gerar esse arquivo automaticamente a partir de um template.

First, copy the version source file `src/hellocopr/pass:[__]initpass:[__].py` to `.tito/templates/pass:[__]initpass:[__].py.template`. Then, open the template file and replace the version string with `$version`. It also makes sense to add a note that the file is managed by tito and should not be edited manually. ``` user@host ~/copr-tito-quickdoc % cat .tito/templates/__init__.py.template ... # This file is automatically created from a template by tito. Do not edit it manually.

__version__ = '$version' ```

Next, add the following to `.tito/tito.props` ```
[version_template]
destination_file = src/hellocopr/__init__.py template_file = .tito/templates/__init__.py.template ``` https://pagure.io/copr-tito-quickdoc/c/28600f6e41d5a4b60f2e47cf077f2fe2d9224e1d?branch=master[Commit the changes]. Now, when we tag a new release, tito will take the template, replace `$version` with whatever version was tagged, and copy the resulting file to `src/hellocopr/pass:[__]initpass:[__].py` before updating the spec file and commiting the changes.

We can test this by tagging a new release:

user@host ~/copr-tito-quickdoc % % tito tag Creating output directory: /tmp/tito Tagging new version of hellocopr: 1.0.1-1 → 1.0.2-1 Created tag: hellocopr-1.0.2-1 View: git show HEAD Undo: tito tag -u Push: git push --follow-tags origin

user@host ~/copr-tito-quickdoc % cat src/hellocopr/init.py …​ # This file is automatically created from a template by tito. Do not edit it manually.

version = '1.0.2' ` If you again push the tag to the remote repo, Copr will again automatically trigger a rebuild.

Release procedure in brief

From now on, updating your software in the Copr repository is as simple as

  1. Commit all changes for your new version.

  2. Perform a test build using tito build --test

  3. Tag the release with tito tag (add --use-version if necessary)

  4. Push the tag to your git repo using git push --follow-tags

and Copr will take care of the rest.

Packaging from source tarballs

You can use a similar process to manage someone elses software on Copr, i.e. build from a tarball downloaded from upstream.

To do so, the following changes need to be made to the procedure described above:

  1. Instead of the unpacked sources, download & commit the source tarball you want to package to your repository

  2. Instead of modifying the source directly, add any changes you need to make in the form of patch files. List these as PatchX: in the spec file

  3. Also in the spec file, set the Version: back to whatever version the program is at and Source0: back to the tarball URL. You can use macros like %{version} for the latter to automatically follow version changes.

  4. Modify tito’s .tito/tito.props to, one, not try to build a source tarball and two, bump the Release: instead of the Version: when tagging

    [buildconfig]
    builder = tito.builder.NoTgzBuilder tagger = tito.tagger.ReleaseTagger ```
    +
    . Don't do any tito templating
    
    The rest of the procedure stays the same. If you make changes to the package without changing the source, you can just tag a new release with tito. If you do update the source tarball, you need to update the `Version:` field and reset `Release:` to `0%\{?dist}` before tagging.
    
    TIP: The tarball-adapted version of the project can be found in the `https://pagure.io/copr-tito-quickdoc/tree/foreign-sources[foreign-sources]` branch of the git repo.