Como eu publico meu software open-source em um repositório Maven?

Um guia passo-a-passo realizado no projeto Java json-formatter-validator

desenvolver um software buscamos utilizar ferramentas que facilitam o gerenciamento, distribuição e evolução do mesmo. Uma das ferramentas mais difundidas na gestão e automação das dependências de um projeto é o Apache Maven. O Apache Maven, ou simplesmente Maven, é uma ferramenta de automação de compilação utilizada inicialmente em projetos Java, mas pode ser utilizada também em outras linguagens como Ruby, Scala e C#, por exemplo.

O Maven utiliza um arquivo no formato XML, chamado de pom.xml (sigla para Project Object Model), em que é possível configurar todo um ambiente de desenvolvimento mais padronizado, aplicando boas práticas de desenvolvimento, permitindo a compilação automatizada do projeto (build) e de gerenciar as versões de bibliotecas e plug-ins dinamicamente, além da distribuição da aplicação em repositórios públicos.

Afinal, como eu publico meu software em um repositório Maven? Como permito que outras pessoas utilizem meu software via dependência no pom.xml? Se você tem interesse ou sempre se perguntou como fazer a publiação de um artefato, este artigo irá te ajudar, com o passo-a-passo nas próximas seções, como é que funciona esse processo. Cabe ressaltar que para executar o passo-a-passo com sucesso, é necessário você ter instalado na sua máquina o JDK, Maven e o Git. Além disso, você precisa ter um usuário no Github e ter o código do projeto commitado no seu repositório.

Como exemplo, utilizarei o fluxo que fiz para meu projeto json-formatter-validator (caso tenham interesse em utilizá-lo, é só clicar no link e ler a documentação disponibilizada no próprio repositório).

Pré-requisitos para publicação

O primeiro passo para publicação é selecionar o repositório que o software será publicado. O mais conhecido é o Maven Central, mas existem outras dezenas disponíveis na web, como o Sonatype Nexus, que será utilizado nesse artigo. O Nexus oferece dois tipos de repositórios: o hosted, que são repositórios em que os artefatos são armazenados localmente no servidor onde o Nexus foi instalado, permitindo que projetos possam publicá-los internamente pela tag distributionManagement no pom.xml (já são pré-configurados os repositórios releases, snapshots e 3rd party); e o proxy, que são repositórios que atuam como intermediários para outros repositórios na web, fazendo o cache dos artefatos (por exemplo, repositório proxy no Nexus apontando para o Maven Central).

Já familiarizados com o Sonatype Nexus, vamos criar uma conta no Sonatype Jira para criação das configurações iniciais do projeto na nuvem.

Tela de login Sonatype Jira

O segundo passo é abrir um jira para a criação do namespace que será usado como seu domínio. E o que seria isso? Consiste em criar seu domínio ou da sua organização. Por exemplo: io.github.mariazevedo88 é o domínio que criei e é vinculado a minha conta pessoal do Github.

Abaixo, segue um exemplo de como preencher o jira:

Exemplo do preenchimento do jira para o namespace io.github.mariazevedo88

Vale lembrar que esse passo deve ser realizado uma única vez para cada domínio. No exemplo acima, foi criado o endereço para qualquer projeto sob o domínio io.github.mariazevedo88.

O terceiro passo é instalar o GNU PG para a criação da chave GPG. É essa chave que vai garantir a autorização para fazer o upload dos artefatos para o Sonatype Nexus. Caso o artefato não esteja assinado com essa chave, não será autorizado a sua publicação.

Em seguida, verifique se o GPG foi instalado corretamente:

Verificando se o GPG foi instalado com sucesso

Confirmada a instalação, basta executar o comando abaixo para gerar a chave.

C:\Users\Mariana>gpg --full-gen-key
gpg (GnuPG) 2.2.11
libgcrypt 1.8.4
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
gpg: keybox 'C:/Users/Mariana/.gnupg/pubring.kbx' created
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
Your selection? 1
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048)
Requested keysize is 2048 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y
GnuPG needs to construct a user ID to identify your key.Real name: Mariana de Azevedo Santos
Email address: SEU_EMAIL
Comment:
You selected this USER-ID:
"Mariana de Azevedo Santos <SEU_EMAIL>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform some other action (type on the keyboard, move the mouse, utilize the disks) during the prime generation; this gives the random number generator a better chance to gain enough entropy.gpg: C:/Users/Mariana/.gnupg/trustdb.gpg: trustdb created
gpg: key XXXXXXXXXXXXXXXX marked as ultimately trusted
gpg: directory 'C:/Users/Mariana/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as 'C:/Users/Mariana/.gnupg/openpgp-revocs.d\SUA_CHAVE_PUBLICA.rev'
public and secret key created and signed.
pub rsa2048 2019-03-03 [SC]
SUA_CHAVE_PUBLICA SERÁ DEMONSTRADA AQUI
uid [ultimate] Mariana de Azevedo Santos <SEU_EMAIL>
sub rsa2048 2019-03-03 [E]

Após criada a chave, é necessário enviá-la para o servidor de verificação executando o comando a seguir:

gpg –keyserver [SERVIDOR] –send-key [SUA_CHAVE_PUBLICA]

No lugar do [SERVIDOR] você utilizar as seguintes opções:

  • gnupg.net:11371
  • keys.pgp.net
  • surfnet.nl
  • mit.edu
  • pool.sks-keyservers.net

Para confirmar se a chave está disponível, pode-se executar o comando abaixo:

$ gpg — keyserver hkp://pool.sks-keyservers.net — recv-keys SUACHAVEPUBLICA
gpg: key xxxxxxxxxxxx: “Mariana de Azevedo Santos <MEU_EMAIL>” not changed
gpg: Total number processed: 1
gpg: unchanged: 1

Após publicação e verificação da disponibilidade da chave GPG, precisamos criar um arquivo chamado settings.xml na pasta .m2 da sua máquina. No momento do deploy, é esse arquivo que o Maven irá consultar para enviar a aplicação para o repositório central. Um exemplo de preenchimento dessa arquivo pode ser visto no código a seguir:

Exemplo da configuração no arquivo settings.xml

Na primeira parte do arquivo, você deverá informar as credenciais de acesso à sua conta, ou seja, usuário e senha criados nos passos anteriores. Na segunda parte do arquivo, são as propriedades da GPG: diretório onde as chaves foram geradas (homedir), identificação da sua chave (keyname), programa executável que irá fazer a autenticação das informações nos artefatos (executable) e senha da sua chave (passphrase).

Configurando o seu projeto

Após as configurações iniciais, precisamos ajustar o pom.xml do projeto para conter informações, plug-ins e dependências que possibilitem a criação de releases e deploy no repositório central corretamente.

Na primeira parte do pom.xml, iremos adicionar informações gerais do projeto como nome, descrição, os desenvolvedores responsáveis, url de acesso ao repositório no Github, licença do projeto, o software de integração contínua utilizado, dados do repositório no Nexus e propriedades das dependências do projeto (versões do projeto). Um exemplo dessa configuração inicial pode ser visto abaixo, no projeto json-formatter-validator.

Exemplo da configuração inicial do pom.xml

Em seguida, é necessário acrescentar as dependências exigidas para o fluxo de geração de releases e deploy automático. São elas:

  • maven-source-plugin: cria o .jar do projeto.
  • maven-release-plugin: executado no goal release, faz a liberação do artefato, basicamente criando uma versão para o seu projeto e atualizando o SCM — Software Configuration Management. Por exemplo, faz as atualizações das tags de versão.
  • maven-deploy-plugin: executado no goal deploy e é responsável por adicionar seu artefato em um repositório remoto.
  • nexus-staging-maven-plugin: usado para fazer o staging do artefato no Nexus. Ele é complementar às funcionalidades do maven-deploy-plugin (foi criado para isso).
Exemplo da configuração do maven-deploy-plugin
Exemplo da configuração do maven-release-plugin
Exemplo da configuração do maven-source-plugin
Exemplo da configuração do nexus-staging-maven-plugin

Por fim, é preciso acrescentar um profile chamado sign-artifacts no pom.xml, contendo informações da chave GPG para assinar os artefatos que serão publicados. Você pode observar, após publicação do artefato, que na sua pasta .m2, que foram gerados vários arquivos com a extensão .asc, correspondentes a cada arquivo enviado para o repositório. São esses arquivos que certificam a autenticidade dos artefatos.

Exemplo dos arquivos disponíveis no repositório local

A versão final do pom.xml do projeto json-formatter-validator pode ser consultada aqui.

Como criar o release e fazer o deploy

Para criar um release, você deve executar o comando:

mvn clean install release:prepare

Com a execução desse comando, o Maven vai limpar o projeto, remover todos os arquivos gerados no build anterior (com o goal = clean), fazer a criação do pacote e “instalação” do mesmo no repositório local (com o goal = install) e preparar o release (atualiza número da versão, a tag e o próximo incremento de versão do SNAPSHOT). Para efetuar o deploy, basta executar o seguinte comando:

mvn release:perform

Com o goal perform, o Maven fará o deploy dos artefatos no Nexus.

Caso opte fazer todo esse processo via Eclipse IDE, por exemplo, você pode criar um build no item Run Configurations para executar todo o processo de uma vez só.

Exemplo de configuração via IDE

Um ponto de atenção nesse processo de envio é garantir que a versão do Java da IDE e do projeto seja a mesma. Além do JDK, revise detalhadamente o seu pom.xml, pois qualquer erro nas informações do projeto barra a publicação do artefato. Por exemplo, no meu primeiro teste, a url do projeto estava errada (hehe).

Caso esteja tudo correto, seu build será bem sucedido e seu projeto estará disponível no Nexus Repository Manager para ser utilizado em outros projetos open-source. Abaixo, um captura do site pode ser vista com as versões do json-formatter-validator.

Exemplo do repositório io.github.mariazevedo88 no Nexus, com o projeto json-formatter-validator

Após a verificação da sua primeira publicação no repositório central, você deve confirmar que o repositório foi publicado com sucesso no jira que foi aberto no Sonatype.

Exemplo de mensagem de confirmação no jira

Da mesma forma, você pode verificar se o projeto já está replicado no Maven Repository, uma vez que o proxy da Nexus distribui pela internet qualquer outro repositório remoto ao nosso.

Exemplo do projeto json-formatter-validator hospedado no Maven Repository

A cereja do bolo é acrescentar o README.md do seu projeto no Github, o badge do Nexus, informando a última versão disponível no repositório.

Exemplo do badge do Nexus no Github

Para isso, utilizei o Shields.io, que fornece badges interessantes e informativos para o seu projeto.

Sobre o projeto utilizado como exemplo, existe uma versão para quem ainda utiliza Java 7. Caso ainda tenham dúvidas sobre todo o processo detalhado no post, deixe seu comentário ou mande um e-mail.

Espero que tenham gostado do post. Abraços!

Referências

  1. Apache Maven: https://maven.apache.org/
  2. Sonatype: https://www.sonatype.com/
  3. Maven Repository: https://mvnrepository.com
  4. The Central Repository: https://central.sonatype.org/pages/apache-maven.html
  5. DZone — Publish Your Artifacts to Maven Central: https://dzone.com/articles/publish-your-artifacts-to-maven-central
  6. Lista de repositórios públicos no Nexus: https://oss.sonatype.org/content/groups/public/

Senior Software Developer/Tech Lead, master in Computer Science/Software Engineering, Java, open source, and software quality enthusiast.

Senior Software Developer/Tech Lead, master in Computer Science/Software Engineering, Java, open source, and software quality enthusiast.