Por que o Gradle Wrapper deve ser comprometido com o VCS?

148

Na documentação de Gradle: https://docs.gradle.org/current/dsl/org.gradle.api.tasks.wrapper.Wrapper.html

Os scripts gerados por esta tarefa devem ser confirmados no seu sistema de controle de versão. Esta tarefa também gera um pequeno arquivo JAR de inicialização e um arquivo de propriedades gradle-wrapper.jar que também deve ser confirmado no seu VCS. Os scripts delegam a este JAR.

De: O que NÃO deve estar sob controle de origem?

Eu acho Generated filesque não deveria estar no VCS.

Quando são gradlewe são gradle/gradle-wrapper.jarnecessários?

Por que não armazenar um gradle versionno build.gradlearquivo?

farmer1992
fonte
1
O que pode ser uma discussão interessante, dadas as respostas abaixo, é a utilidade desses arquivos se você estiver usando algum tipo de ferramenta de integração contínua. Quais procurarão o invólucro de qualidade e o usarão se estiver lá?
lilbyrdie

Respostas:

124

Como o objetivo principal do wrapper gradle é poder, sem ter instalado o gradle e sem saber como ele funciona, de onde fazer o download, de qual versão, para clonar o projeto do VCS, para executar o script gradlew contém e para construir o projeto sem nenhuma etapa adicional.

Se tudo o que você tinha era um número de versão gradle em um arquivo build.gradle, você precisaria de um README explicando a todos que a versão X gradle deve ser baixada da URL Y e instalada, e você teria que fazer isso toda vez que a versão for incrementada.

JB Nizet
fonte
94
Isso é estupido. O gradle-wrapper.jar não deve ser necessário no VCS. Gradle deve poder baixar qualquer versão depois de instalar a primeira, se necessário. O conjunto de ferramentas não tem nada a ver com um VCS ... Entendo que sua resposta está certa, e é o design de Gradle. Mas esse design é absurdo.
precisa saber é o seguinte
26
O objetivo é poder fazer o download do gradle sem ter o instalado antes. Qual é o problema em ter um arquivo grande de 50 KB no VCS?
JB Nizet
59
O problema é que não faz parte do projeto. É uma ferramenta que você usa para criar o projeto. Você não armazenará o JDK no VCS, não é? Nem GCC para uma aplicação C? Então, por que você armazenaria uma peça Gradle? Se um desenvolvedor não conseguir ler e instalar o próprio Gradle, isso é outro problema.
Marc Plano-Lesay
26
O problema também é que você não consegue se lembrar, 2 anos após o lançamento, qual versão do Gradle foi usada para criar a versão v1.0 do seu software, que você precisa corrigir para um cliente que ainda esteja usando este 1.0 versão e não pode atualizar. O wrapper gradle resolve isso: você clona a tag 1.0 do VCS, constrói-a usando gradlew e usa a versão gradle usada há 2 anos para compilar a versão 1.0.
JB Nizet
33
Concordo que a versão Gradle a ser usada precisa ser indicada em algum lugar do projeto. Mas o Gradle é uma ferramenta externa , nada comparável a um README ou a qualquer coisa que você listou. Gradle deve conseguir buscar a versão correspondente, sem precisar armazenar um jar no VCS.
precisa saber é o seguinte
80

Porque todo o objetivo do invólucro gradle é poder, sem ter instalado o gradle

O mesmo argumento vale para o JDK, você deseja confirmar isso também? Você também confirma todas as suas bibliotecas de dependência?

As dependências devem ser atualizadas continuamente à medida que novas versões são lançadas. Para obter segurança e outras correções de bugs. E porque se você ficar para trás, pode ser uma tarefa muito demorada se atualizar novamente.

Se o wrapper gradle for incrementado para cada nova versão e for confirmado, o repositório crescerá muito. O problema é óbvio ao trabalhar com VCS distribuído, em que um clone baixa todas as versões de tudo.

e sem nem mesmo saber como funciona

Crie um script de construção que faça o download do wrapper e use-o para construir. Todo mundo não precisa saber como o script funciona, eles precisam concordar que o projeto é construído executando-o.

, de onde baixá-lo, qual versão

task wrapper(type: Wrapper) {
 gradleVersion = 'X.X' 
}

E depois

gradle wrapper

Para baixar a versão correta.

, para clonar o projeto do VCS, executar o script gradlew que ele contém e criar o projeto sem nenhuma etapa adicional.

Resolvido pelas etapas acima. O download do wrapper gradle não é diferente do download de outras dependências. O script pode ser inteligente o suficiente para verificar se há algum wrapper gradle atual e fazer o download apenas se houver uma nova versão.

Se o desenvolvedor nunca usou o Gradle antes e talvez não saiba que o projeto é construído com o Gradle. Então é mais óbvio executar um "build.sh" comparado com o "gradlew build".

Se tudo o que você tinha era um número de versão gradle em um arquivo build.gradle, você precisaria de um README explicando a todos que a versão gradle X deve ser baixada da URL Y e instalada,

Não, você não precisaria de um README. Você poderia ter um, mas somos desenvolvedores e devemos automatizar o máximo possível. Criar um script é melhor.

e você teria que fazer isso toda vez que a versão for incrementada.

Se os desenvolvedores concordarem que o processo correto é:

  1. Repo clone
  2. Executar script de construção

Então, atualizar para o wrapper gradle mais recente não é problema. Se a versão for incrementada desde a última execução, o script poderá baixar a nova versão.

Tomas Bjerre
fonte
2
"As dependências devem ser atualizadas continuamente." Sim, em uma direção voltada para o futuro. Não, em uma direção voltada para trás. Para reproduzir uma compilação antiga, você precisa ter versões específicas das dependências. Gradle torna alguns tipos de projetos mais rápidos e fáceis de lidar. Seria uma bagunça em uma organização que precisava de reprodução e auditoria.
lilbyrdie
3
Não tenho muita certeza do que você quer dizer. Mas se você possui build.gradlecontrole de versão e possui: task wrapper(type: Wrapper) { gradleVersion = 'X.X' } Em seguida gradle wrapper, baixará o wrapper que foi usado e você poderá reproduzir a compilação antiga.
Tomas Bjerre
1
Estava se referindo à sua linha sobre as dependências, não a versão gradle. Claro, você deseja que suas bibliotecas tenham todas as mais recentes correções de segurança e bug, mas NÃO quando estiver tentando reproduzir uma compilação antiga, talvez para fins legais ou de auditoria. Você deseja que suas bibliotecas e processo de construção possam produzir uma saída idêntica binária, se possível. Como na dependência de uma biblioteca, não há garantia de que uma versão específica esteja disponível no momento da criação ... seja daqui a duas semanas ou daqui a duas décadas. Então, sim, é o mesmo que bibliotecas e SDKs, para alguns projetos.
lilbyrdie
3
Eu acho que o invólucro existe principalmente por razões históricas. No começo, todo mundo usa o Maven e ninguém tem o Gradle instalado. Seria difícil convencer um colega de trabalho a instalar dependências intrusivas desconhecidas, para que o wrapper os ajude a inicializar. Hoje em dia todo mundo já tem Gradle, e o invólucro se torna redundante.
Franklin Yu
1
Você está sugerindo executar o gradle wrapperclone após cada compilação? Isso basicamente torna o invólucro inútil, porque o ponto principal é que você não precisa instalar o Gradle localmente para criar o projeto !
Xerus
41

Eu gostaria de recomendar uma abordagem simples.

No README do seu projeto, documente que uma etapa da instalação é necessária, a saber:

gradle wrapper --gradle-version 3.3

Isso funciona com o Gradle 2.4 ou superior. Isso cria um wrapper sem exigir que uma tarefa dedicada seja adicionada ao "build.gradle".

Com esta opção, ignore (não faça check-in) estes arquivos / pastas para controle de versão:

  • ./gradle
  • gradlew
  • gradlew.bat

O principal benefício é que você não precisa fazer o check-in de um arquivo baixado para o controle de origem. Custa uma etapa extra na instalação. Eu acho que vale a pena.

David J.
fonte
15
por que você precisaria de wrapper então? Toda a idéia do wrapper é que você pode criar um projeto sem ter gradle em seu sistema.
Edio 21/11
4
Ótima solução. Sem binários no git e ainda uma capacidade de usar gradlew. @edio, você precisará baixar e usar uma versão específica do gradle.
18718 Kirill
3

O que é o "projeto"?

Talvez haja uma definição técnica desse idioma que exclua os scripts de construção. Mas se aceitarmos essa definição, devemos dizer que seu "projeto" não é tudo o que você precisa para a versão!

Mas se dissermos "seu projeto" é tudo o que você fez . Então podemos dizer que você deve incluí- lo e somente ele no VCS.

Isso é muito teórico e talvez não seja prático no caso de nossos trabalhos de desenvolvimento. Então, alteramos para " seu projeto é todo arquivo (ou pasta) necessário para editá-los diretamente ".

"diretamente" significa "não indiretamente" e "indiretamente" significa editando outro arquivo e, em seguida, um efeito será refletido nesse arquivo .

Portanto, chegamos ao mesmo que o OP disse (e é dito aqui ):

Eu acho que os arquivos gerados não devem estar no VCS.

Sim. Porque você não os criou. Portanto, eles não fazem parte do "seu projeto" de acordo com a segunda definição.


Qual é o resultado desses arquivos:

  • build.gradle : Sim. Precisamos editá-lo. Nossos trabalhos devem ser versionados.

    Nota: Não há diferença em onde você o edita. Seja no seu ambiente de editor de texto ou no ambiente da GUI do Project Structure . Enfim, você está fazendo isso diretamente !

  • gradle-wrapper.properties : Sim. Precisamos pelo menos determinar a versão Gradle neste arquivo.

  • gradle-wrapper.jar e gradlew [.bat] : Eu não os criei ou editei em nenhum dos meus trabalhos de desenvolvimento até o momento! Então a resposta é "Não". Se você fez isso, a resposta é "Sim" sobre você nesse trabalho (e sobre o mesmo arquivo que você editou).


A observação importante sobre o caso mais recente é que o usuário que clona seu repositório precisa executar este comando nos repositórios<root-directory> para gerar automaticamente arquivos wrapper:

> gradle wrapper --gradle-version=$v --distribution-type=$distType

$ve $distTypesão determinados em gradle-wrapper.properties :

distributionUrl=https\://services.gradle.org/distributions/gradle-{$v}-{$distType}.zip

Consulte https://gradle.org/install/ para obter mais informações.

gradle executável é bin/gradle[.bat] na distribuição local. Não é necessário que a distribuição local seja a mesma que a determinada no repo. Após a criação dos arquivos wrapper , é gradlew[.bat]possível fazer o download da distribuição Gradle determinada automaticamente (se não existir localmente). Então ele / ela provavelmente deve gerar novamente os arquivos do wrapper usando o novo gradleexecutável (na distribuição baixada) usando as instruções acima.


Nota: Nas instruções acima, o usuário deve ter pelo menos um distribuição Gradle localmente (por exemplo ~/.gradle/wrapper/dists/gradle-4.10-bin/bg6py687nqv2mbe6e1hdtk57h/gradle-4.10). Abrange quase todos os casos reais. Mas o que acontece se o usuário ainda não tiver distribuição?

Ele / ela pode fazer o download manualmente usando o URL no .propertiesarquivo. Mas se ele / ela não o localizar no caminho que o invólucro esperado, a embalagem vai baixá-lo novamente! O caminho esperado é completamente previsível, mas está fora do assunto (veja aqui a parte mais complexa).

Existem também algumas maneiras mais fáceis (mas sujas). Por exemplo, ele / ela pode copiar arquivos de invólucro (exceto .propertiesarquivo) de qualquer outro repositório local / remoto para seu repositório e, em seguida, executar gradlewem seu repositório. Ele fará o download automático da distribuição adequada.

Mir-Ismaili
fonte
1

De acordo com os documentos da Gradle , gradle-wrapper.jaré esperado adicionar ao VCS, pois disponibilizar o Gradle Wrapper para desenvolvedores faz parte da abordagem da Gradle:

Para disponibilizar os arquivos Wrapper para outros desenvolvedores e ambientes de execução, você precisará verificá-los no controle de versão. Todos os arquivos Wrapper, incluindo o arquivo JAR, são muito pequenos. A inclusão do arquivo JAR no controle de versão é esperada. Algumas organizações não permitem que os projetos enviem arquivos binários ao controle de versão. No momento, não há opções alternativas para a abordagem.

Arthur Khazbs
fonte
1

Pergunta antiga, nova resposta. Se você não atualiza o gradle com frequência (a maioria de nós não), é melhor enviá-lo para o VCS. E o principal motivo para mim é aumentar a velocidade de compilação no servidor de CI. Atualmente, a maioria dos projetos está sendo criada e instalada por servidores de CI, sempre diferentes instâncias de servidor.

Se você não confirmar, o servidor de CI fará o download de um jar para cada build e aumentará significativamente o tempo de build. Existem outras maneiras de lidar com esse problema, mas considero a mais fácil de manter.

smgn
fonte