Auto: Supprimer l'exigence pour maven-release-plugin

Créé le 26 mai 2020  ·  44Commentaires  ·  Source: intuit/auto

J'ai commencé le travail de refactorisation du plugin auto maven pour essayer d'être plus cohérent avec le reste de auto . Ce faisant, je suis arrivé à quelques conclusions.

L'exigence actuelle pour auto avec le plugin maven est que le projet utilise le maven-release-plugin . Cela a plusieurs conséquences qui en font un mauvais ajustement pour auto .

La fonctionnalité principale du maven-release-plugin exécute les étapes suivantes via release:prepare :

  1. Vérifiez qu'il n'y a pas de modifications non validées dans les sources
  2. Vérifiez qu'il n'y a pas de dépendances SNAPSHOT
  3. Changer la version dans les POM de x-SNAPSHOT vers une nouvelle version
  4. Transformez les informations SCM dans le POM pour inclure la destination finale de la balise
  5. Exécutez les tests du projet sur les POM modifiés pour confirmer que tout est en ordre de marche
  6. Valider les POM modifiés
  7. Marquez le code dans le SCM avec un nom de version
  8. Bump la version dans les POM à une nouvelle valeur y-SNAPSHOT
  9. Valider les POM modifiés

Et puis une release se fait via release:perform :

  1. Paiement à partir d'une URL SCM avec balise facultative
  2. Exécutez les objectifs Maven prédéfinis pour publier le projet (par défaut, deploy site-deploy )

Afin de s'assurer que le plugin se comporte d'une manière cohérente avec auto , l'implémentation actuelle utilise du hack git pour éliminer les commits effectués par le but release:prepare . En d'autres termes, le maven-release-plugin fait le travail pour lequel le auto est conçu, et doit donc être « contourné » d'une manière moins que gracieuse.

La méthode utilisée pour extraire le référentiel et les informations sur l'auteur est tout aussi importante - actuellement, le plugin maven utilise les sections <scm/> et <developers/> des pom.xml pour dériver ces informations. Cela s'écarte de la méthodologie utilisée par le reste de auto qui utilise les métadonnées git. L'implémentation actuelle présente plusieurs problèmes :

  1. Le author est défini via la section <developers/> du pom.xml , ce qui signifie que la personne qui effectue le commit NE PEUT PAS être la même que le author . Il n'y a aucune tentative d'aligner l'auteur du commit git avec les informations <developers/> .
  2. Les informations owner et repo sont définies via la section <scm/> , qui peut être différente du référentiel réel et du propriétaire du clone actuel.

En approfondissant le plugin et en le comparant au plugin gradle , il semble que le seul objectif du maven-release-plugin qui serait bénéfique soit le release:update-versions but. Cet objectif pourrait facilement être remplacé par une manipulation XML simple.

Compte tenu des frais généraux liés au maintien du maven-release-plugin et de l'avantage minimal, je pense que l'exigence devrait être levée et que le plugin auto maven devrait être implémenté dans un auto -mode autochtone.

enhancement released

Tous les 44 commentaires

Je suis complètement d'accord!

La plupart de vos points avec les informations que je reçois du pom.xml sont probablement liés à ma mauvaise compréhension de ces champs. Tout changement ici est plus que bienvenu.

Je suis tout à fait pour tous les changements de rupture que nous devons faire. Nous pouvons probablement lancer certains des plus petits changements de rupture détaillés dans #1156

Il semble que mes deux points concernant <scm/> et <developers/> soient incorrects. Le plugin npm extrait ceux du package.json . Cela signifie-t-il qu'ils _devraient_ se trouver dans le pom.xml ?

Si ce sont les équivalents pom des champs npm repository et author alors oui.

L'auteur est défini via le section du pom.xml, ce qui signifie que la personne qui effectue le commit PEUT NE PAS être la même que l'auteur sélectionné. Il n'y a aucune tentative d'aligner l'auteur du commit git avec le informations.

Ceci est également vrai pour le plugin npm. Localement auto ne remplacera pas votre configuration git , mais dans un environnement CI, il devra peut-être définir le author pour commit`.

Les informations sur le propriétaire et le repo sont définies via le section, qui peut être différente du référentiel réel et du propriétaire du clone actuel.

Serait-ce différent ? Dans le monde npm, le champ repository pointe généralement vers le code du package. En pratique, on n'exécute généralement pas auto sur un fork et s'ils le faisaient, j'espère qu'ils mettront à jour le champ repository dans leur fork

D'accord, cela a du sens - le comportement approprié consiste donc à rechercher ces éléments (actuels), et s'ils ne sont PAS trouvés dans le pom.xml , retournez et supposez qu'ils ont été définis dans le .autorc (nouveau comportement).

Actuellement, le plugin produira une erreur s'il ne trouve pas les sections <scm/> et <developers/> dans le pom.xml .

Ah oui c'est définitivement un bug. Il ne devrait pas générer d'erreurs https://github.com/intuit/auto/blob/master/plugins/npm/src/index.ts#L504

Existe-t-il un moyen d'obtenir la version NUMBER de auto d'une manière lisible par machine ? J'ai été surpris que la commande auto version produise le TYPE de version bump, plutôt que le nombre.

Vous pouvez utiliser --quiet et il n'imprimera que la version produite par la commande. ou associez-le à --dry-run et vous pourrez voir quelle version sera publiée ensuite.

Je serais peut-être prêt à ajouter un indicateur pour faire cracher version la version actuelle. Cela devient juste bizarre dans les scénarios multi-paquets

Je peux voir ça. Il est probablement préférable de laisser à l'appelant le soin de déterminer quelle version il recherche.

Votre point sur les scénarios multi-paquets est pertinent ici - le maven-release-plugin prend en charge ce type de scénario, prêt à l'emploi. Cela me fait me demander si je voudrais reproduire ce travail. Je me retrouve un peu dans une impasse - d'une part, mon argument pour NE PAS utiliser le maven-release-plugin est valide, tandis que d'autre part, des choses comme la gestion de version de sous-module sont un cas d'utilisation non trivial qui doit être adressé, et est couvert par le maven-release-plugin.

J'ai trouvé deux méthodes d'utilisation du plug-in maven-release qui pourraient être utilisées pour empêcher le plug-in maven de modifier le référentiel pendant release:prepare , et je les testerai plus tard dans la journée.

@hipstersmoothie J'ai une question sur le comportement des crochets getAuthor , getRepo , etc. - RE: le commentaire sur https://github.com/intuit/auto/issues/1260#issuecomment - 634280655, je regarde les tests et ils semblent contredire cela.

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

Ainsi, lorsque je renvoie un undefined AuthorInformation aucune erreur n'est renvoyée.

Des suggestions sur ce que je fais peut-être mal, ou si je devrais réintroduire throw dans ma gestion des crochets ?

C'est définitivement faux étant donné le fonctionnement de tous les autres plugins. Revenir indéfini est la bonne façon. De cette façon, core peut revenir à l'utilisateur git configuré en local si nécessaire

Gotcha - c'est ce que j'ai pensé, j'ai donc modifié les tests pour m'assurer que les hooks échoués renvoient undefined .

On dirait que les plugins gradle et cocopods génèrent des erreurs s'ils ne trouvent pas de version. J'ai créé un bug pour le plugin gradle - en voulez-vous un autre pour les cocopods ?

Laissez juste un pas sur la question. Merci pour la capture !

J'ai du mal avec une bonne méthode pour tester l'initialisation des valeurs pendant hooks.beforeRun . Plus précisément, j'ai le code suivant qui, lorsqu'il est sous débogage, extrait avec succès les informations sur l'auteur lors du tap hooks.beforeRun , mais échoue au test :

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

Ce qui se passe, c'est que le test arrive au hook getAuthor AVANT que le hook beforeRun soit exécuté. J'ai regardé d'autres codes qui testent cela (gradle, s3) et je n'ai pas de chance.

Fondamentalement, j'ai besoin d'un moyen d'exécuter de manière déterministe le crochet beforeRun et je ne sais pas comment le faire.

pousse une branche et je peux le vérifier

@hipstersmoothie voici la branche : https://github.com/terradatum/auto/tree/remove-maven-release-plugin-requirement

J'ai commenté le code qui pousserait mes modifications vers le référentiel central afin que je puisse tester le code sur un projet réel sans polluer l'historique distant.

Toute aide que vous pouvez m'apporter est grandement appréciée - j'aimerais pouvoir utiliser les tests pour vérifier dans quelle mesure je peux modifier les fichiers pom.xml, plutôt que de recourir à la méthode à l'ancienne de "exécuter le code contre fichiers réels, vérifiez les fichiers réels, exécutez git reset --hard HEAD~1 pour vous débarrasser des modifications, rincez et répétez."

De plus, j'ai dû apporter quelques modifications au package.json local qui étaient incompatibles avec la racine package.json afin d'exécuter les tests de plaisanterie dans IntelliJ - pouvez-vous me donner des conseils à ce sujet, ou devrait-il "juste fonctionner" hors de la boîte ?

Plus précisément, lorsque vous êtes dans le répertoire du plugin maven et que vous exécutez npm test - TOUS les tests finissent par s'exécuter car "test": "jest --maxWorkers=2 --config ../../package.json" .

Et si j'essaye d'utiliser IntelliJ Test Runner de l'éditeur, j'obtiens :

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

Je peux résoudre mon problème avec IntelliJ en ajoutant un fichier 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
}

Et puis en ajoutant jest-circus aux fichiers racine ou maven package.json .

Je viens de remarquer que xml2js ne fera pas le travail car il SUPPRIMERA silencieusement tous les commentaires XML pendant les traductions XML => JSON => XML. J'ai essayé de le faire fonctionner, et c'est comme arracher des dents. Il n'y a aucune garantie que le XML ressemblera à l'original lors du déplacement dans les transformations xml2js , et c'est un problème.

Pour exécuter des tests pour un seul plugin, je l'exécute à partir de la racine.

yarn test plugins/maven

Cela soulève alors la question de savoir si vous pouvez facilement afficher tous les changements que vous feriez ou les artefacts que vous construirez sans réellement faire de changements.

Cela semble être un assez gros problème. Existe-t-il une interface de ligne de commande standard livrée dans des environnements Java qui permet de modifier ce fichier ?

Pour les plugins qui n'ont pas d'analyseur pour le fichier de configuration (ex : ruby) auto utilise principalement regex pour mettre à jour le fichier.

Avez-vous eu l'occasion de regarder le beforeRun ? J'ai une solution de contournement, mais ça me semble vraiment bidon...

Je n'aime vraiment pas l'idée d'utiliser regex avec XML - c'est sujet aux erreurs et fragile. Cependant, il semble également ridiculement complexe d'essayer d'utiliser un DOMParser ou un XMLSerializer juste pour modifier la version, c'est pourquoi j'essayais de travailler avec xml2js en premier lieu.

Regarde ça maintenant !

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

Le problème est que vous faites un tap "synchrone" et que vous faites un travail asynchrone à l'intérieur de celui-ci

Change ça

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

pour ça

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

Ah, le hook avant l'exécution est synchronisé en ce moment, c'est le vrai problème. Cela ne changerait rien si cela devenait un AsyncSeriesHook au lieu d'un SyncHook . Je peux pousser un commit vers votre branche si ce que je dis n'est pas clair

S'il vous plaît, laissez-moi vous faire un contributeur.

Vas-y!

Juste poussé. A couru les tests et seulement deux échouent maintenant. le hook beforeRun fonctionne comme prévu.

@hipstersmoothie Je ne vois pas le commit au dépôt terradatum/auto ?

maintenant j'ai poussé

Cela entraînera-t-il un changement radical pour tout plugin qui utilise actuellement le robinet synchrone ?

Nan. les robinets de synchronisation devraient fonctionner de la même manière. Cela ajoute simplement la possibilité d'exploiter une promesse

J'ai réussi à faire ce travail avec une regex fragile / sujette aux erreurs. Mon souci est que l'élément <version/> est utilisé PARTOUT dans un fichier pom.xml - pour la version d'artefact ET pour les dépendances et les plugins. En d'autres termes, l'expression régulière est très susceptible de modifier par inadvertance une version qu'elle n'est pas censée modifier.

En essayant de travailler avec XML DOM (via xmldom, xmldom-ts, xml2js, xml2json, etc.), je me suis retrouvé coincé dans un bourbier aux proportions épiques. Je ne me considère en aucun cas comme un expert en dactylographie ou en javascript, alors c'est peut-être là que je tombe.

Deux choses me bottent le cul :

  1. Je ne peux pas comprendre comment faire en sorte qu'IntelliJ exécute les tests maven (et UNIQUEMENT les tests maven) en mode débogage. Parfois ça marche, parfois non.
  2. Chargez le pom.xml dans un Document puis utilisez xpath pour sélectionner les nœuds "/project/version" et "/project/parent/version".

Entre ces deux problèmes, j'ai probablement passé 12 à 16 heures au total, et je deviens vraiment frustré. J'avais le numéro 1 qui travaillait jusqu'à ce matin, et je pense que le numéro 2 devrait être relativement simple, mais il semble me battre à chaque tournant.

Je suis enclin à revenir à l'utilisation de maven-release-plugin pour la raison ridiculement simple qu'il gère la mise à jour des fichiers pom.xml pour moi.

Je ne peux pas comprendre comment faire en sorte qu'IntelliJ exécute les tests maven (et UNIQUEMENT les tests maven) en mode débogage. Parfois ça marche, parfois non.

Je suis désolé, je ne suis pas plus d'une aide ici. J'utilise VSCode et débogue rarement les tests. Pouvez-vous exécuter à partir de la racine avec yarn test plugins/maven ?

Chargez le pom.xml dans un document puis utilisez xpath pour sélectionner les nœuds "/project/version" et "/project/parent/version".

Cela semble être une bonne méthode. Si cela peut fonctionner, cela semble bien.

Je suis enclin à revenir à l'utilisation de maven-release-plugin pour la raison ridiculement simple qu'il gère la mise à jour des fichiers pom.xml pour moi.

Existe-t-il uniquement des éléments basés sur des plugins tels que https://stackoverflow.com/questions/5726291/updating-version-numbers-of-modules-in-a-multi-module-maven-project disponibles pour maven ? une chose basée sur mvn de bas niveau serait parfaite.


BTW merci d'avoir passé autant de temps là-dessus !

Merci pour les commentaires et le soutien. Désolé pour la diatribe (ish) commentaire précédent.

Excellent point sur les versions-maven-plugin - je n'ai jamais travaillé avec et je n'avais aucune idée qu'il existait. Cela me facilitera certainement les choses... C'est un compromis parfait entre le maven-release-plugin et essayer de gérer les fichiers pom.xml via le plugin auto.

Je peux faire travailler yarn test plugins/maven . Je suis aussi un grand fan de l'utilisation du débogueur pour inspecter les choses, plutôt que le console.log plus traditionnel, c'est donc probablement là que je me cause plus de brûlures d'estomac que j'en ai besoin...

Après un voyage long et ardu, j'ai presque ce que je considère comme une solution complète, qui modifiera directement les fichiers pom.xml ou utilisera le versions-maven-plugin pour définir les versions.

Il y a quelques mises en garde. Le code utilisé pour modifier le pom.xml fonctionne avec un DOM, ce qui a les conséquences suivantes :

  1. Il y a un bogue dans le traitement de tsconfig.json qui nécessite que la lib "dom" soit avant "es2017" dans "compilerOptions" :

travaux:

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

ne fonctionne pas :

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

Sans le "correctif", ce qui suit se produit :

$ 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. Les tests jest nécessitent testEnvironment: 'jsdom' par opposition à 'node' .

Sans le "correctif", ce qui suit se produit :

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

Aucun des "correctifs" ci-dessus ne fonctionne lorsqu'il est défini dans les configurations racine du plugin, par exemple ni plugins/maven/tsconfig.json ni une configuration jest dans plugins/maven/package.json . Les modifications apportées aux fichiers de configuration racine n'ont pas semblé affecter négativement les tests ou les fonctionnalités.

c'est sur ta branche ? Je peux probablement résoudre ce problème

Pas encore... Je m'assure que tous les tests (et les nouveaux) passent avant de pousser. Je vous contacterai lorsqu'ils seront prêts à être évalués.

Je viens de rebaser master sur ma branche, et maintenant j'obtiens plusieurs erreurs de construction.

Tout d'abord, le fichier yarn.lock été interrompu à cause d'un conflit de fusion, j'ai donc dû le supprimer et le reconstruire :

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

Une fois que j'ai fait cela, j'obtiens maintenant des erreurs @octokit/graphql :

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

J'avais bon espoir de pouvoir créer un PR pour cela - mais je crains que ce ne soit pas encore prêt.

D'accord, j'ai trouvé ce que je devais faire - je viens d'extraire le fichier yarn.lock de master , puis j'ai réexécuté yarn clean && yarn install && yarn build && yarn test plugins/maven et je pense que je suis prêt à -aller.

Impressionnant! Je vais revoir ça aujourd'hui. Désolé de ne pas avoir répondu ce week-end !


:rocket: Le numéro est sorti en v9.40.0 :rocket:

Cette page vous a été utile?
0 / 5 - 0 notes