Auto: Remover o requisito para maven-release-plugin

Criado em 26 mai. 2020  ·  44Comentários  ·  Fonte: intuit/auto

Comecei o trabalho de refatoração do plug-in auto maven para tentar ser mais consistente com o resto de auto . Ao fazer isso, cheguei a algumas conclusões.

O requisito atual para auto com o plugin maven é que o projeto use o maven-release-plugin . Isso tem várias consequências que o tornam um ajuste inadequado para auto .

A funcionalidade principal do maven-release-plugin executa as seguintes etapas por meio de release:prepare :

  1. Verifique se não há mudanças não confirmadas nas fontes
  2. Verifique se não há dependências SNAPSHOT
  3. Altere a versão nos POMs de x-SNAPSHOT para uma nova versão
  4. Transforme as informações do SCM no POM para incluir o destino final da tag
  5. Execute os testes do projeto nos POMs modificados para confirmar se tudo está funcionando bem
  6. Confirme os POMs modificados
  7. Identifique o código no SCM com um nome de versão
  8. Aumente a versão nos POMs para um novo valor y-SNAPSHOT
  9. Confirme os POMs modificados

E então uma liberação é feita por meio de release:perform :

  1. Check-out de um URL SCM com tag opcional
  2. Execute as metas predefinidas do Maven para liberar o projeto (por padrão, deploy site-deploy )

Para garantir que o plug-in se comporte de maneira consistente com auto , a implementação atual usa algum hackery git para descartar os commits feitos pela meta release:prepare . Em outras palavras, maven-release-plugin está fazendo o trabalho para o qual auto foi projetado e, portanto, deve ser "contornado" de uma maneira nada elegante.

De igual importância é o método usado para extrair o repositório e as informações do autor - atualmente, o plugin maven usa as seções <scm/> e <developers/> de pom.xml para derivar essa informação. Isso se desvia da metodologia usada pelo restante de auto que usa metadados git. A implementação atual tem vários problemas:

  1. O author é definido através da seção <developers/> de pom.xml , o que significa que a pessoa que está fazendo o commit PODE ser a mesma que o author selecionado. Não há tentativa de alinhar o autor do git commit com as informações de <developers/> .
  2. As informações de owner e repo são definidas por meio da seção <scm/> , que pode ser diferente do repositório real e do proprietário do clone atual.

Ao fazer um mergulho mais profundo no plug-in e compará-lo com o plug-in gradle , parece que o único objetivo do maven-release-plugin que seria benéfico é o release:update-versions meta. Esse objetivo pode ser facilmente substituído por algum tratamento XML simples.

Dada a sobrecarga de manutenção de maven-release-plugin e a vantagem mínima, minha opinião é que o requisito deve ser eliminado e o plug-in auto maven deve ser implementado em mais auto moda nativa.

enhancement released

Todos 44 comentários

Eu concordo completamente!

A maioria dos seus pontos com as informações que obtenho do pom.xml provavelmente está ligada ao meu mal-entendido sobre esses campos. Quaisquer alterações aqui são mais do que bem-vindas.

Sou totalmente a favor de quaisquer mudanças significativas que tenhamos que fazer. Provavelmente podemos lançar algumas das mudanças menores detalhadas em # 1156

Parece que meus dois pontos sobre <scm/> e <developers/> estão incorretos. O plugin npm puxa aqueles do package.json . Isso significa que eles _devem_ estar localizados em pom.xml ?

Se esses forem os pom equivalentes dos campos npm repository e author , então sim.

O autor é definido por meio do seção do pom.xml, o que significa que a pessoa que está fazendo o commit NÃO PODE ser a mesma do autor selecionado. Não há tentativa de alinhar o autor do git commit com o em formação.

Isso também é válido para o plug-in npm. Localmente automático não substituirá sua configuração git , mas em um ambiente de CI pode ser necessário definir author para confirmar`.

As informações do proprietário e do repo são definidas por meio do seção, que pode ser diferente do repositório real e proprietário do clone atual.

Isso seria diferente? No mundo npm, o campo repository geralmente aponta para o código do pacote. Na prática, geralmente não se executa auto em um fork e, se o fizesse, espero que atualizem o campo repository para seu fork

Ok, isso faz sentido - então o comportamento adequado é procurar por essas coisas (atuais), e se elas NÃO forem encontradas em pom.xml , retorne e assuma que foram definidas em .autorc (novo comportamento).

Atualmente, o plug-in apresentará um erro se não encontrar as seções <scm/> e <developers/> em pom.xml .

Sim, isso é definitivamente um bug. Não deve lançar erros https://github.com/intuit/auto/blob/master/plugins/npm/src/index.ts#L504

Existe uma maneira de obter a versão NUMBER de auto de forma legível por máquina? Fiquei surpreso que o comando auto version produza o TIPO de aumento de versão, em vez do número.

Você pode usar --quiet e só imprimirá a versão produzida pelo comando. ou emparelhe-o com --dry-run e você pode ver qual versão será publicada a seguir.

Eu poderia estar disposto a adicionar um sinalizador para fazer version cuspir a versão real. Isso só fica estranho em cenários de vários pacotes

Eu posso ver isso. Provavelmente, é melhor deixar isso para o chamador descobrir qual versão ele está procurando.

Seu ponto sobre cenários de múltiplos pacotes é pertinente aqui - o maven-release-plugin suporta esse tipo de cenário, pronto para uso. Isso me faz questionar se eu gostaria de reproduzir aquele trabalho. Estou me encontrando em um impasse - por um lado, meu argumento para NÃO usar o plugin maven-release é válido, enquanto por outro, coisas como gerenciamento de versão de submódulo é um caso de uso não trivial que deve ser endereçado, e é coberto pelo maven-release-plugin.

Eu encontrei dois métodos de uso do plugin maven-release que podem ser usados ​​para evitar que o plugin maven modifique o repositório durante release:prepare , e irei testá-los ainda hoje.

@hipstersmoothie Tenho uma pergunta sobre o comportamento dos ganchos getAuthor , getRepo , etc. - RE: o comentário sobre https://github.com/intuit/auto/issues/1260#issuecomment - 634280655, estou olhando os testes e eles parecem contradizer isso.

Exemplo:
https://github.com/intuit/auto/blob/47d3b54ef1a7af990fe0ca898e747dd833fde3b1/plugins/maven/__tests__/maven.test.ts#L95

Portanto, quando eu retorno um undefined AuthorInformation nenhum erro é gerado.

Alguma sugestão sobre o que posso estar fazendo de errado ou se devo reintroduzir throw no manuseio do gancho?

Isso está definitivamente errado, considerando como todos os outros plug-ins funcionam. Retornar indefinido é o caminho certo. Dessa forma, core pode recorrer ao usuário git configurado local se necessário

Peguei você - foi isso que imaginei, então modifiquei os testes para garantir que os ganchos com falha retornem undefined .

Parece que os plug-ins gradle e cocoapods apresentam erros se não encontrarem uma versão. Eu criei um bug para o plugin gradle - você quer outro para cocoapods?

Apenas deixe um não sobre o assunto. Obrigado pela pegadinha!

Estou lutando com um bom método para testar a inicialização de valores durante hooks.beforeRun . Especificamente, eu tenho o seguinte código, que quando sob depuração extrai com sucesso as informações do autor durante o toque hooks.beforeRun , mas falha no teste:

    test("should get author from pom.xml", async () => {
      mockRead(`
        <project
          xmlns="http://maven.apache.org/POM/4.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
          <developers>
            <developer>
              <name>Andrew Lisowski</name>
              <email>[email protected]</email>
            </developer>
          </developers>
        </project>
      `);

      await hooks.beforeRun.promise({} as any);

      expect(await hooks.getAuthor.promise()).toStrictEqual(
        expect.objectContaining({
          email: "[email protected]",
          name: "Andrew Lisowski",
        })
      );
    });

O que está acontecendo é que o teste está chegando ao gancho getAuthor ANTES do gancho beforeRun ser executado. Já olhei outro código que testa isso (gradle, s3) e não estou tendo sorte.

Basicamente, preciso de uma maneira determinística de executar o gancho beforeRun e não consigo descobrir como fazê-lo.

empurre um galho e eu posso dar uma olhada

@hipstersmoothie, aqui está o branch: https://github.com/terradatum/auto/tree/remove-maven-release-plugin-requirement

Comentei o código que enviaria minhas alterações para o repositório central para que eu pudesse testar o código em um projeto real sem poluir o histórico remoto.

Qualquer ajuda que você possa me dar com isso é muito apreciada - eu adoraria poder usar os testes para verificar o quão bem posso modificar os arquivos pom.xml, em vez de recorrer ao método da velha escola de "executar o código contra arquivos reais, verifique os arquivos reais, execute git reset --hard HEAD~1 para se livrar das alterações, enxágue e repita. "

Além disso, tive que fazer algumas alterações no package.json que eram incompatíveis com a raiz package.json para executar os testes de jest no IntelliJ - há alguma orientação que você possa me dar sobre isso, ou deveria "simplesmente funcionar" fora da caixa?

Especificamente, quando no diretório do plugin maven e executando npm test - TODOS os testes acabam sendo executados porque "test": "jest --maxWorkers=2 --config ../../package.json" .

E se tento usar o IntelliJ Test Runner do editor, obtenho:

  ● Test suite failed to run

    SyntaxError: /home/rbellamy/Development/Terradatum/auto/plugins/maven/__tests__/maven.test.ts: Unexpected token, expected "," (15:24)

      13 | }));
      14 | 
    > 15 | const mockRead = (result: string) =>
         |                         ^
      16 |   jest
      17 |     .spyOn(fs, "readFile")
      18 |     // @ts-ignore

      at Parser._raise (../../node_modules/@babel/parser/src/parser/location.js:241:45)
      at Parser._raise [as raiseWithData] (../../node_modules/@babel/parser/src/parser/location.js:236:17)
      at Parser.raiseWithData [as raise] (../../node_modules/@babel/parser/src/parser/location.js:220:17)
      at Parser.raise [as unexpected] (../../node_modules/@babel/parser/src/parser/util.js:149:16)
      at Parser.unexpected [as expect] (../../node_modules/@babel/parser/src/parser/util.js:129:28)
      at Parser.expect [as parseParenAndDistinguishExpression] (../../node_modules/@babel/parser/src/parser/expression.js:1293:14)
      at Parser.parseParenAndDistinguishExpression [as parseExprAtom] (../../node_modules/@babel/parser/src/parser/expression.js:1029:21)
      at Parser.parseExprAtom [as parseExprSubscripts] (../../node_modules/@babel/parser/src/parser/expression.js:539:23)
      at Parser.parseExprSubscripts [as parseMaybeUnary] (../../node_modules/@babel/parser/src/parser/expression.js:519:21)
      at Parser.parseMaybeUnary [as parseExprOps] (../../node_modules/@babel/parser/src/parser/expression.js:311:23)

Posso resolver meu problema com o IntelliJ adicionando um arquivo jest.config.ts :

module.exports = {
  clearMocks: true,
  moduleFileExtensions: ['js', 'ts'],
  testEnvironment: 'node',
  testMatch: ['**/*.test.ts'],
  testRunner: 'jest-circus/runner',
  transform: {
    '^.+\\.ts$': 'ts-jest'
  },
  verbose: true
}

E então adicionar jest-circus aos arquivos raiz ou maven package.json .

Apenas notei que xml2js não fará o trabalho porque ele REMOVERÁ silenciosamente todos os comentários XML durante as traduções XML => JSON => XML. Tenho tentado fazer funcionar e é como arrancar dentes. Não há garantia de que o XML ficará parecido com o original ao passar pelas transformações xml2js , e isso é um quebra-negócio.

Para executar testes para apenas um plugin, eu o executo da raiz.

yarn test plugins/maven

Isso, então, levanta a questão de saber se você pode ou não mostrar facilmente todas as mudanças que faria ou os artefatos que estaria construindo sem realmente fazer algumas mudanças.

Isso parece um grande problema. Existe algum CLI padrão fornecido em ambientes java que permite a edição desse arquivo?

Para plug-ins que não têm um analisador para o arquivo de configuração (ex: ruby) auto usa principalmente regex para atualizar o arquivo.

Você teve a chance de olhar para o problema de beforeRun ? Eu tenho uma solução alternativa, mas parece realmente hacky ...

Eu realmente não gosto da ideia de usar regex com XML - é suscetível a erros e frágil. No entanto, também parece ridiculamente complexo tentar usar DOMParser ou XMLSerializer apenas para modificar a versão, e é por isso que eu estava tentando trabalhar com xml2js em primeiro lugar.

Olhando para isso agora!

https://github.com/terradatum/auto/blob/remove-maven-release-plugin-requirement/plugins/maven/src/index.ts#L127

O problema é que você está fazendo um toque "síncrono" e um trabalho assíncrono dentro dele

Mude isso

auto.hooks.beforeRun.tap(this.name, async () => {

para isso

auto.hooks.beforeRun.tapPromise(this.name, async () => {

Ah, o hook before run está sincronizado agora, esse é o problema real. Não mudaria nada se isso se tornasse AsyncSeriesHook vez de SyncHook . Posso enviar um commit para o seu branch se não estiver claro o que estou dizendo

Por favor ... deixe-me torná-lo um colaborador.

Vá em frente!

Apenas empurrou. Fiz os testes e apenas dois estão falhando agora. o gancho beforeRun está funcionando conforme o esperado.

@hipstersmoothie Não vejo o commit para o terradatum / repo automático?

agora eu realmente empurrei

Isso causará uma alteração significativa para qualquer plug-in que esteja usando o toque síncrono?

Não. os toques de sincronização devem funcionar da mesma forma. Isso apenas adiciona a capacidade de cumprir uma promessa

Fiz este trabalho com sucesso com regex frágil / sujeito a erros. Minha preocupação é que o elemento <version/> seja usado EM TODOS OS LUGARES em um arquivo pom.xml - para a versão do artefato E para as dependências e plug-ins. Em outras palavras, é muito provável que o regex altere inadvertidamente uma versão que não deveria.

Ao tentar trabalhar com XML DOM (via xmldom, xmldom-ts, xml2js, xml2json, etc), me vi preso em um atoleiro de proporções épicas. De forma alguma me considero um especialista em datilografia ou em javascript, então talvez seja aí que estou caindo.

Duas coisas estão me chutando:

  1. Não consigo descobrir como fazer com que o IntelliJ execute os testes do maven (e SOMENTE os testes do maven) no modo de depuração. Às vezes funciona, às vezes não.
  2. Carregando o pom.xml em um Document e então use o xpath para selecionar os nós "/ project / version" e "/ project / parent / version".

Entre essas duas edições, provavelmente passei de 12 a 16 horas no total e estou ficando muito frustrado. Eu tinha o # 1 trabalhando até esta manhã e acho que o # 2 deveria ser relativamente simples, mas parece estar lutando contra mim a cada passo.

Estou inclinado a voltar a usar o plugin maven-release pelo motivo ridiculamente simples de que ele lida com a atualização dos arquivos pom.xml para mim.

Não consigo descobrir como fazer com que o IntelliJ execute os testes do maven (e SOMENTE os testes do maven) no modo de depuração. Às vezes funciona, às vezes não.

Me desculpe, eu não sou mais uma ajuda aqui. Eu uso o VSCode e raramente depuro os testes. Você pode executar a partir do root com yarn test plugins/maven ?

Carregando o pom.xml em um documento e, em seguida, use o xpath para selecionar os nós "/ project / version" e "/ project / parent / version".

Este parece ser um bom método. Se isso pudesse funcionar, parece bom.

Estou inclinado a voltar a usar o plugin maven-release pelo motivo ridiculamente simples de que ele lida com a atualização dos arquivos pom.xml para mim.

Há apenas coisas baseadas em plug-ins como https://stackoverflow.com/questions/5726291/updating-version-numbers-of-modules-in-a-multi-module-maven-project disponíveis para maven? uma coisa baseada em mvn de baixo nível seria perfeita.


BTW, obrigado por gastar tanto tempo nisso!

Obrigado pelo feedback e suporte. Desculpe pelo comentário anterior retórico (ish).

Excelente ponto sobre o versions-maven-plugin - eu não trabalhei com ele antes e não tinha ideia de que ele existia. Isso certamente tornará as coisas mais fáceis para mim ... É um compromisso perfeito entre o plugin maven-release e tentar gerenciar os arquivos pom.xml através do plugin automático.

Posso fazer yarn test plugins/maven funcionar. Também sou um grande fã de usar o depurador para inspecionar as coisas, em vez do mais tradicional console.log , então é provavelmente onde estou causando mais azia do que preciso ...

Depois de uma longa e árdua jornada, quase tenho o que considero uma solução completa, que irá modificar os arquivos pom.xml diretamente ou usar versions-maven-plugin para definir as versões.

Existem algumas ressalvas. O código usado para modificar o pom.xml está funcionando com um DOM, o que tem as seguintes consequências:

  1. Há um bug no processamento de tsconfig.json que requer que "dom" lib esteja antes de "es2017" em "compilerOptions" :

trabalho:

"compilerOptions": [ "dom", "es2017" ]

não funciona:

"compilerOptions": [ "es2017", "dom" ]

Sem a "correção", ocorre o seguinte:

$ tsc -b tsconfig.dev.json
node_modules/@types/jsdom/index.d.ts:28:40 - error TS2304: Cannot find name 'DocumentFragment'.

28         static fragment(html: string): DocumentFragment;
                                          ~~~~~~~~~~~~~~~~

node_modules/@types/jsdom/index.d.ts:45:28 - error TS2304: Cannot find name 'Node'.

45         nodeLocation(node: Node): ElementLocation | null;
                              ~~~~

node_modules/@types/jsdom/index.d.ts:188:19 - error TS2304: Cannot find name 'HTMLScriptElement'.

188         element?: HTMLScriptElement | HTMLLinkElement | HTMLIFrameElement | HTMLImageElement;
                      ~~~~~~~~~~~~~~~~~

node_modules/@types/jsdom/index.d.ts:188:39 - error TS2304: Cannot find name 'HTMLLinkElement'.

188         element?: HTMLScriptElement | HTMLLinkElement | HTMLIFrameElement | HTMLImageElement;
                                          ~~~~~~~~~~~~~~~
<snip - numerous other errors>
  1. Os testes de jest requerem testEnvironment: 'jsdom' em oposição a 'node' .

Sem a "correção", ocorre o seguinte:

$ jest --runInBand plugins/maven
 FAIL  plugins/maven/__tests__/maven.test.ts
  maven
    updatePomVersion
      ✕ should replace the previousVersion with the newVersion (39ms)

  ● maven › updatePomVersion › should replace the previousVersion with the newVersion

    ReferenceError: XPathEvaluator is not defined

      51 | ) => {
      52 |   const pomDom = new jsdom.JSDOM(content, {contentType: "text/xml"}).window.document;
    > 53 |   const evaluator = new XPathEvaluator();
         |                     ^
      54 |   const resolver = evaluator.createNSResolver(pomDom.documentElement);
      55 |   const expression = evaluator.createExpression("/project/version", resolver);
      56 |   const versionNode = expression.evaluate(pomDom.documentElement, XPathResult.FIRST_ORDERED_NODE_TYPE);

      at Object.exports.updatePomVersion (plugins/maven/src/index.ts:53:21)
      at Object.test (plugins/maven/__tests__/maven.test.ts:53:26)

Nenhuma das "correções" acima funciona quando definida nas configurações raiz do plug-in, por exemplo, nem plugins/maven/tsconfig.json nem uma configuração jest em plugins/maven/package.json . Fazer as alterações nos arquivos de configuração raiz não pareceu afetar negativamente os testes ou a funcionalidade.

está no seu ramo? Provavelmente posso consertar isso

Ainda não ... Estou garantindo que todos os testes (e os novos) sejam aprovados antes de empurrar. Vou enviar um ping quando eles estiverem prontos para revisão.

Acabei de realocar o master em meu branch e agora estou recebendo vários erros de compilação.

Primeiro, o arquivo yarn.lock foi interrompido devido a um conflito de mesclagem, então tive que excluí-lo e reconstruí-lo:

error Incorrect integrity when fetching from the cache for "babel-plugin-jest-hoist". Cache has "sha512-u+/W+WAjMlvoocYGTwthAiQSxDcJAyHpQ6oWlHdFZaaN+Rlk8Q7iiwDPg2lN/FyJtAYnKjFxbn7xus4HCFkg5g== sha1-EpyAulx/x1uvOkW5Pi43LVfKJnc=" and remote has "sha512-+AuoehOrjt9irZL7DOt2+4ZaTM6dlu1s5TTS46JBa0/qem4dy7VNW3tMb96qeEqcIh20LD73TVNtmVEeymTG7w==". Run `yarn cache clean` to fix the problem

Depois de fazer isso, estou recebendo @octokit/graphql erros:

$ tsc -b tsconfig.dev.json
packages/core/src/auto.ts:2018:13 - error TS2571: Object is of type 'unknown'.

2018         if (result?.[`hash_${commit}`]) {
                 ~~~~~~

packages/core/src/auto.ts:2019:27 - error TS2571: Object is of type 'unknown'.

2019           const number = (result[`hash_${commit}`] as ISearchResult).edges[0]
                               ~~~~~~

packages/core/src/release.ts:286:52 - error TS2769: No overload matches this call.
  Overload 1 of 2, '(o: ArrayLike<unknown> | { [s: string]: unknown; }): [string, unknown][]', gave the following error.
    Argument of type 'unknown' is not assignable to parameter of type 'ArrayLike<unknown> | { [s: string]: unknown; }'.
      Type 'unknown' is not assignable to type '{ [s: string]: unknown; }'.
  Overload 2 of 2, '(o: {}): [string, any][]', gave the following error.
    Argument of type 'unknown' is not assignable to parameter of type '{}'.

286       (acc, result) => [...acc, ...(Object.entries(result) as QueryEntry[])],
                                                       ~~~~~~


packages/core/src/__tests__/git.test.ts:209:12 - error TS2571: Object is of type 'unknown'.

209     expect(result!.data).not.toBeUndefined();
               ~~~~~~~


Found 4 errors.

error Command failed with exit code 2.

Eu estava super esperançoso de ser capaz de criar um PR para isso - mas estou preocupado que ainda não esteja pronto.

Ok, descobri o que precisava fazer - acabei de verificar o arquivo yarn.lock de master e, em seguida, executei novamente yarn clean && yarn install && yarn build && yarn test plugins/maven e acho que estou pronto -ir.

Incrível! Vou revisar isso hoje. Desculpe, não respondi no fim de semana!


: rocket: O problema foi lançado em v9.40.0 : rocket:

Esta página foi útil?
0 / 5 - 0 avaliações