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
:
Et puis une release se fait via release:perform
:
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 :
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/>
.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.
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.
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 !
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 :
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 :
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>
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: