Auto: Eliminar el requisito de maven-release-plugin

Creado en 26 may. 2020  ·  44Comentarios  ·  Fuente: intuit/auto

Comencé el trabajo de refactorizar el complemento auto maven para tratar de ser más consistente con el resto de auto . Al hacerlo, he llegado a algunas conclusiones.

El requisito actual para auto con el complemento maven es que el proyecto use maven-release-plugin . Esto tiene varias consecuencias que lo hacen un mal ajuste para auto .

La funcionalidad principal de maven-release-plugin ejecuta los siguientes pasos a través de release:prepare :

  1. Compruebe que no haya cambios no confirmados en las fuentes.
  2. Compruebe que no haya dependencias SNAPSHOT
  3. Cambie la versión en los POM de x-SNAPSHOT a una nueva versión
  4. Transforme la información de SCM en el POM para incluir el destino final de la etiqueta
  5. Ejecute las pruebas del proyecto con los POM modificados para confirmar que todo funciona correctamente.
  6. Confirmar los POM modificados
  7. Etiquete el código en el SCM con un nombre de versión
  8. Aumente la versión en los POM a un nuevo valor y-SNAPSHOT
  9. Confirmar los POM modificados

Y luego se realiza un lanzamiento a través de release:perform :

  1. Pago desde una URL de SCM con etiqueta opcional
  2. Ejecute los objetivos predefinidos de Maven para lanzar el proyecto (de forma predeterminada, deploy site-deploy )

Para garantizar que el complemento se comporte de manera coherente con auto , la implementación actual utiliza algunos git hackery para deshacerse de las confirmaciones realizadas por el objetivo release:prepare . En otras palabras, el maven-release-plugin está haciendo el trabajo para el que está diseñado auto y, por lo tanto, tiene que "solucionarse" de una manera menos elegante.

De igual importancia es el método utilizado para extraer el repositorio y la información del autor; actualmente, el complemento maven usa las secciones <scm/> y <developers/> de pom.xml para derivar Esa información. Esto se desvía de la metodología utilizada por el resto de auto que usa metadatos de git. La implementación actual tiene varios problemas:

  1. El author se establece a través de la sección <developers/> de pom.xml , lo que significa que la persona que realiza la confirmación NO PUEDE ser la misma que el author . No se intenta alinear el autor de la confirmación de git con la información <developers/> .
  2. La información owner y repo se establece a través de la sección <scm/> , que puede ser diferente del repositorio y propietario real del clon actual.

Al hacer un análisis más profundo del complemento, y al compararlo con el complemento gradle , parece que el único objetivo de maven-release-plugin que sería de beneficio es el release:update-versions objetivo. Ese objetivo podría reemplazarse fácilmente con un simple manejo de XML.

Dada la sobrecarga de mantener el maven-release-plugin y la ventaja mínima, mi opinión es que el requisito debe eliminarse, y el complemento auto maven debe implementarse en un auto - moda nativa.

enhancement released

Todos 44 comentarios

¡Estoy completamente de acuerdo!

La mayoría de sus puntos con la información que obtengo del pom.xml probablemente estén relacionados con mi malentendido de esos campos. Cualquier cambio aquí es más que bienvenido.

Estoy totalmente a favor de cualquier cambio importante que tengamos que hacer. Probablemente podamos lanzar algunos de los cambios de ruptura más pequeños detallados en el n. ° 1156

Parece que mis dos puntos sobre <scm/> y <developers/> son incorrectos. El complemento npm extrae del package.json . ¿Significa esto que _deben_ estar ubicados en el pom.xml ?

Si esos son los pom equivalentes de los campos npm repository y author , entonces sí.

El autor se establece a través del sección del pom.xml, lo que significa que la persona que realiza la confirmación NO PUEDE ser la misma que el autor seleccionado. No hay ningún intento de alinear el autor de git commit con el información.

Esto también es cierto para el complemento npm. Localmente auto no anulará su configuración git , pero en un entorno CI puede que tenga que configurar author para confirmar`.

La información del propietario y del repositorio se establece a través del sección, que puede ser diferente al repositorio real y al propietario del clon actual.

¿Sería esto diferente? En npm world, el campo repository generalmente apunta al código del paquete. En la práctica, uno generalmente no ejecuta auto en un fork y si lo hicieran, espero que actualicen el campo repository en su fork

Está bien, eso tiene sentido, por lo que el comportamiento adecuado es buscar esas cosas (actuales), y si NO se encuentran en el pom.xml , regrese y asuma que se han establecido en el .autorc (nuevo comportamiento).

Actualmente, el complemento generará un error si no encuentra las secciones <scm/> y <developers/> en las pom.xml .

Ah, sí, eso es definitivamente un error. No debe arrojar errores https://github.com/intuit/auto/blob/master/plugins/npm/src/index.ts#L504

¿Hay alguna manera de obtener la versión NUMBER de auto de forma legible por máquina? Me sorprendió que el comando auto version produzca el TIPO de aumento de versión, en lugar del número.

Puede usar --quiet y solo imprimirá la versión producida por el comando. o combínelo con --dry-run y podrá ver qué versión se publicará a continuación.

Podría estar dispuesto a agregar una bandera para hacer que version escupe la versión real. Esto se vuelve extraño en escenarios de paquetes múltiples

Puedo ver eso. Probablemente sea mejor dejar eso a la persona que llama para que averigüe qué versión está buscando.

Su punto sobre los escenarios de paquetes múltiples es pertinente aquí: el complemento de lanzamiento de maven admite ese tipo de escenario, listo para usar. Esto me hace cuestionar si me gustaría reproducir ese trabajo. Me encuentro en un punto muerto: por un lado, mi argumento para NO usar maven-release-plugin es válido, mientras que, por el otro, cosas como la administración de versiones de submódulos es un caso de uso no trivial que debe abordarse y está cubierto por el complemento maven-release-plugin.

Encontré dos métodos para usar el complemento maven-release-plugin que podrían usarse para evitar que el complemento maven modifique el repositorio durante release:prepare , y los probaré más tarde hoy.

@hipstersmoothie Tengo una pregunta sobre el comportamiento de los ganchos de getAuthor , getRepo , etc. - RE: el comentario sobre https://github.com/intuit/auto/issues/1260#issuecomment - 634280655, estoy mirando las pruebas y parecen contradecir eso.

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

Entonces, cuando devuelvo un undefined AuthorInformation no se produce ningún error.

¿Alguna sugerencia sobre lo que puedo estar haciendo mal o si debo volver a introducir throw en el manejo de mi gancho?

Eso es definitivamente incorrecto dado cómo funcionan todos los demás complementos. Regresar sin definir es el camino correcto. De esa manera core puede recurrir al usuario git configurado localmente si es necesario

Entendido, eso es lo que pensé, así que modifiqué las pruebas para garantizar que los ganchos fallidos devuelvan undefined .

Parece que los complementos de gradle y cocoapods arrojan errores si no pueden encontrar una versión. Creé un error para el complemento de gradle: ¿quieres otro para cocoapods?

Simplemente deje un no en el tema. ¡Gracias por la captura!

Estoy luchando con un buen método para probar la inicialización de valores durante hooks.beforeRun . Específicamente, tengo el siguiente código, que cuando está bajo depuración extrae con éxito la información del autor durante el tap hooks.beforeRun , pero falla la prueba:

    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",
        })
      );
    });

Lo que está sucediendo es que la prueba está llegando al gancho getAuthor ANTES de que se ejecute el gancho beforeRun . He visto otro código que prueba esto (gradle, s3) y no estoy teniendo suerte.

Básicamente, necesito una forma de ejecutar de manera determinista el gancho beforeRun y no puedo averiguar cómo hacerlo.

empuja una rama y puedo comprobarlo

@hipstersmoothie aquí está la rama: https://github.com/terradatum/auto/tree/remove-maven-release-plugin-requirement

He comentado el código que enviaría mis cambios al repositorio central para poder probar el código en un proyecto real sin contaminar el historial remoto.

Cualquier ayuda que pueda brindarme con esto es muy apreciada; me encantaría poder usar las pruebas para verificar qué tan bien puedo modificar los archivos pom.xml, en lugar de recurrir al método de la vieja escuela de "ejecutar el código contra archivos reales, verifique los archivos reales, ejecute git reset --hard HEAD~1 para deshacerse de los cambios, enjuague y repita. "

Además, tuve que hacer algunos cambios en el package.json local que eran incompatibles con la raíz package.json para ejecutar las pruebas de broma en IntelliJ: ¿hay alguna guía que pueda darme al respecto? ¿O debería "simplemente funcionar" fuera de la caja?

Específicamente, cuando está en el directorio de complementos de Maven y ejecuta npm test - TODAS las pruebas terminan ejecutándose porque "test": "jest --maxWorkers=2 --config ../../package.json" .

Y si trato de usar IntelliJ Test Runner desde el editor, obtengo:

  ● 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)

Puedo resolver mi problema con IntelliJ agregando un archivo 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
}

Y luego agregando jest-circus a los archivos root o maven package.json .

Acabo de notar que xml2js no va a hacer el trabajo porque ELIMINARÁ silenciosamente todos los comentarios XML durante las traducciones XML => JSON => XML. He intentado que funcione y es como sacar dientes. No hay garantía de que el XML se parezca en algo al original cuando se mueva a través de las transformaciones xml2js , y eso es un factor decisivo.

Para ejecutar pruebas para un solo complemento, lo ejecuto desde la raíz.

yarn test plugins/maven

Esto luego plantea la pregunta de si puede o no mostrar fácilmente todos los cambios que estaría haciendo o los artefactos que estaría construyendo sin realmente hacer algunos cambios.

Eso parece un factor decisivo. ¿Existe alguna CLI estándar enviada en entornos Java que permita la edición de ese archivo?

Para los complementos que no tienen un analizador para el archivo de configuración (por ejemplo: ruby) auto usa principalmente expresiones regulares para actualizar el archivo.

¿Tuviste la oportunidad de ver el problema beforeRun ? Tengo una solución, pero se siente realmente horrible ...

Realmente no me gusta la idea de usar expresiones regulares con XML: es propenso a errores y frágil. Sin embargo, también parece ridículamente complejo intentar usar DOMParser o XMLSerializer solo para modificar la versión, por lo que estaba tratando de trabajar con xml2js en primer lugar.

¡Mirando esto ahora!

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

El problema es que estás haciendo un toque "sincrónico" y haciendo un trabajo asincrónico dentro de él.

Cambia esto

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

a esto

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

Ah, el gancho antes de ejecutar está sincronizado en este momento, ese es el verdadero problema. No cambiaría nada si se convirtiera en AsyncSeriesHook lugar de SyncHook . Puedo enviar un compromiso a su rama si no está claro lo que estoy diciendo

Por favor, hazlo ... déjame convertirte en colaborador.

¡Adelante!

Solo empujado. Ejecuté las pruebas y ahora solo dos fallan. el gancho beforeRun funciona como se esperaba.

@hipstersmoothie ¿No veo el compromiso con el repositorio terradatum / auto?

ahora realmente he empujado

¿Causará eso un cambio importante para cualquier complemento que esté utilizando actualmente el grifo síncrono?

No. Los grifos de sincronización deberían funcionar igual. Esto solo agrega la capacidad de aprovechar una promesa

He logrado que esto funcione con expresiones regulares frágiles / propensas a errores. Mi preocupación es que el elemento <version/> se usa EN TODAS PARTES en un archivo pom.xml , para la versión del artefacto Y para las dependencias y complementos. En otras palabras, es muy probable que la expresión regular cambie inadvertidamente una versión que no debería.

Al intentar trabajar con XML DOM (a través de xmldom, xmldom-ts, xml2js, xml2json, etc.), me encontré atrapado en un atolladero de proporciones épicas. De ninguna manera me considero un experto en mecanografiado o javascript, así que tal vez ahí es donde me estoy cayendo.

Dos cosas me están pateando el trasero:

  1. No puedo averiguar cómo hacer que IntelliJ ejecute las pruebas de maven (y SOLO las pruebas de maven) en modo de depuración. A veces funciona, a veces no.
  2. Cargando el pom.xml en un Document y luego use xpath para seleccionar los nodos "/ project / version" y "/ project / parent / version".

Entre esos dos problemas, probablemente he pasado de 12 a 16 horas en total, y me estoy frustrando mucho. Tenía el # 1 trabajando hasta esta mañana, y creo que el # 2 debería ser relativamente simple, pero parece estar peleando conmigo a cada paso.

Me inclino a volver a usar maven-release-plugin por la razón ridículamente simple de que se encarga de actualizar los archivos pom.xml por mí.

No puedo averiguar cómo hacer que IntelliJ ejecute las pruebas de maven (y SOLO las pruebas de maven) en modo de depuración. A veces funciona, a veces no.

Lo siento, no soy de mayor ayuda aquí. Utilizo VSCode y rara vez depuro las pruebas. ¿Puedes ejecutar desde root con yarn test plugins/maven ?

Cargar el pom.xml en un documento y luego usar xpath para seleccionar los nodos "/ project / version" y "/ project / parent / version".

Parece un buen método. Si eso pudiera funcionar, parece bueno.

Me inclino a volver a usar maven-release-plugin por la razón ridículamente simple de que se encarga de actualizar los archivos pom.xml por mí.

¿Solo hay material basado en complementos como https://stackoverflow.com/questions/5726291/updating-version-numbers-of-modules-in-a-multi-module-maven-project disponible para maven? una cosa basada en mvn de bajo nivel sería perfecta.


Por cierto, ¡gracias por dedicar tanto tiempo a esto!

Gracias por los comentarios y el apoyo. Perdón por el comentario anterior despotricando (ish).

Un gran punto sobre las versiones-maven-plugin: no he trabajado con él antes y no tenía idea de que existía. Eso ciertamente me facilitará las cosas ... Es un compromiso perfecto entre el complemento de lanzamiento de maven y tratar de administrar los archivos pom.xml a través del complemento automático.

Puedo hacer que yarn test plugins/maven funcione. También soy un gran admirador de usar el depurador para inspeccionar cosas, en lugar del más tradicional console.log , así que probablemente es ahí donde me estoy causando más acidez de la que necesito ...

Después de un largo y arduo viaje, casi tengo lo que considero una solución completa, que modificará los archivos pom.xml directamente o usará versions-maven-plugin para configurar versiones.

Hay algunas advertencias. El código utilizado para modificar pom.xml está funcionando con un DOM, lo que tiene las siguientes consecuencias:

  1. Hay un error en el procesamiento de tsconfig.json que requiere que "dom" lib esté antes de "es2017" en "compilerOptions" :

obras:

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

no funciona:

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

Sin la "corrección", ocurre lo siguiente:

$ 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. Las pruebas jest requieren testEnvironment: 'jsdom' en lugar de 'node' .

Sin la "corrección", ocurre lo siguiente:

$ 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)

Ninguna de las "correcciones" anteriores funciona cuando se establece en las configuraciones raíz del complemento, por ejemplo, ni plugins/maven/tsconfig.json ni una configuración de jest en plugins/maven/package.json . Hacer los cambios en los archivos de configuración raíz no pareció afectar negativamente las pruebas o la funcionalidad.

¿Está esto en tu sucursal? Probablemente pueda arreglar esto

Todavía no ... Me estoy asegurando de que todas las pruebas (y las nuevas) pasen antes de seguir adelante. Te enviaré un ping cuando estén listos para que los revises.

Acabo de volver a basar el maestro en mi rama y ahora recibo varios errores de compilación.

Primero, el archivo yarn.lock se bloqueó debido a un conflicto de fusión, así que tuve que eliminarlo y reconstruirlo:

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

Una vez que hice eso, ahora recibo @octokit/graphql errores:

$ 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.

Tenía muchas esperanzas de poder crear un RP para esto, pero me preocupa que aún no esté listo.

De acuerdo, resolví lo que tenía que hacer: simplemente revisé el archivo yarn.lock de master y luego volví a ejecutar yarn clean && yarn install && yarn build && yarn test plugins/maven y creo que estoy bien -ir.

¡Impresionante! Revisaré esto hoy. ¡Siento no haber respondido durante el fin de semana!


: rocket: El problema se publicó en v9.40.0 : rocket:

¿Fue útil esta página
0 / 5 - 0 calificaciones