Go: cmd/go : ajout de la prise en charge de la version du package à la chaîne d'outils Go

Créé le 7 mars 2018  ·  242Commentaires  ·  Source: golang/go

proposition : ajouter la prise en charge de la version du package à la chaîne d'outils Go

Il est grand temps d'ajouter des versions au vocabulaire de travail des développeurs Go et de nos outils.
La proposition liée décrit une façon de le faire. Voir en particulier la section Justification pour une discussion sur les alternatives.

Ce problème GitHub est destiné à la discussion sur le fond de la proposition.

Autres références:

Proposal Proposal-Accepted modules

Commentaire le plus utile

Cette proposition a fait l'objet de discussions actives pendant plus de deux mois : @rsc et @spf13 ont organisé des séances de rétroaction et recueilli des commentaires précieux de la communauté qui ont abouti à des révisions de la proposition. @rsc a également tenu des réunions hebdomadaires avec @sdboyer afin d'obtenir de plus amples commentaires. Des commentaires précieux ont été fournis sur la proposition, ce qui a donné lieu à des révisions supplémentaires. De plus en plus, ces commentaires portent sur la mise en œuvre qui l'accompagne plutôt que sur la proposition. Après un examen approfondi, nous pensons qu'il est temps d'accepter cette proposition et de laisser le vaste écosystème de développeurs d'outils de Go commencer à effectuer des ajustements critiques afin que notre base d'utilisateurs puisse avoir la meilleure expérience possible.

Il y a eu deux objections à cette proposition dont nous estimons que nous devrions parler :

  1. La proposition obligera les gens à changer certaines de leurs pratiques concernant l'utilisation et la publication de bibliothèques.
  2. La proposition ne fournit pas de solution technique à tous les scénarios possibles impliquant des incompatibilités.

Ceux-ci sont précis dans leur observation mais fonctionnent comme prévu. Les auteurs et les utilisateurs de code _devront_ changer certaines de leurs pratiques concernant l'utilisation et la publication de bibliothèques, tout comme les développeurs se sont adaptés à d'autres détails de Go, tels que l'exécution de gofmt. Changer les meilleures pratiques est parfois la bonne solution. De même, vgo n'a pas besoin de gérer toutes les situations possibles impliquant des incompatibilités. Comme Russ l'a souligné lors de sa récente conférence à Gophercon Singapore , la seule solution permanente à l'incompatibilité est de travailler ensemble pour corriger l'incompatibilité et maintenir l'écosystème du package Go. Les solutions de contournement temporaires dans un outil comme vgo ou dep n'ont besoin de fonctionner que suffisamment longtemps pour donner aux développeurs le temps de résoudre le vrai problème, et vgo fait assez bien ce travail.

Nous apprécions tous les commentaires et la passion que vous avez apportés à ce problème critique. La proposition a été acceptée.

— Le comité d'examen des propositions Go

Tous les 242 commentaires

Questions fréquemment posées

Ce commentaire de problème répond aux questions les plus fréquemment posées, qu'elles proviennent de la discussion ci-dessous ou d'autres discussions. D'autres questions de la discussion sont dans le commentaire du prochain numéro.

Pourquoi la proposition n'est-elle pas « use Dep » ?

Au début du voyage qui a conduit à cette proposition, il y a près de deux ans, nous pensions tous que la réponse serait de suivre l'approche de gestion des versions de packages illustrée par Ruby's Bundler puis Rust's Cargo : des versions sémantiques étiquetées, un fichier de contraintes de dépendance édité à la main. connu sous le nom de manifeste, une description de dépendance transitive distincte générée par la machine connue sous le nom de fichier de verrouillage, un solveur de version pour calculer un fichier de verrouillage satisfaisant le manifeste et des référentiels comme unité de gestion des versions. Dep suit presque exactement ce plan approximatif et était à l'origine destiné à servir de modèle pour l'intégration de la commande go. Cependant, plus je comprenais les détails de l'approche Bundler/Cargo/Dep et ce qu'ils signifieraient pour Go, en particulier dans la commande go, et plus je discutais de ces détails avec d'autres membres de l'équipe Go, quelques-uns des détails semblait de moins en moins un bon choix pour Go. La proposition ajuste ces détails dans l'espoir de fournir un système plus facile à comprendre et à utiliser pour les développeurs. Consultez la section sur la justification de la proposition pour en savoir plus sur les détails spécifiques que nous voulions modifier, ainsi que le billet de blog annonçant la proposition .

Pourquoi les numéros de version majeurs doivent-ils apparaître dans les chemins d'importation ?

Pour suivre la règle de compatibilité d'importation , ce qui simplifie considérablement le reste du système. Voir également le billet de blog annonçant la proposition , qui en dit plus sur la motivation et la justification de la règle de compatibilité d'importation.

Pourquoi les versions majeures v0 et v1 sont-elles omises des chemins d'importation ?

v1 est omis des chemins d'importation pour deux raisons. Tout d'abord, de nombreux développeurs créeront des packages qui n'apporteront jamais de changement majeur une fois qu'ils auront atteint la v1, ce que nous encourageons depuis le début. Nous ne pensons pas que tous ces développeurs devraient être obligés d'avoir une v1 explicite alors qu'ils n'ont peut-être pas l'intention de publier une v2. Le v1 devient juste du bruit. Si ces développeurs créent finalement une v2, la précision supplémentaire entre alors en jeu, pour la distinguer de la valeur par défaut, la v1. Il y a de bons arguments sur la stabilité visible pour mettre la v1 partout, et si nous concevions un système à partir de zéro, cela en ferait peut-être un appel proche. Mais le poids du code existant fait fortement pencher la balance en faveur de l'omission de la v1.

v0 est omis des chemins d'importation car - selon semver - il n'y a aucune garantie de compatibilité pour ces versions. Exiger un élément v0 explicite ne ferait pas grand-chose pour assurer la compatibilité ; il faudrait dire v0.1.2 pour être tout à fait précis, mettant à jour tous les chemins d'importation à chaque mise à jour de la bibliothèque. Cela semble exagéré. Au lieu de cela, nous espérons que les développeurs regarderont simplement la liste des modules dont ils dépendent et se méfieront de manière appropriée des versions v0.xy qu'ils trouveront.

Cela a pour effet de ne pas distinguer v0 de v1 dans les chemins d'importation, mais généralement v0 est une séquence de changements de rupture menant à v1, il est donc logique de traiter v1 comme la dernière étape de cette séquence de rupture, pas quelque chose qui doit être distingué de v0 . Comme l'a dit @Merovius (https://github.com/golang/go/issues/24301#issuecomment-376213693):

En utilisant la v0.x, vous acceptez que la v0.(x+1) puisse vous obliger à corriger votre code. Pourquoi est-ce un problème si v0.(x+1) s'appelle plutôt v1.0 ?

Enfin, l'omission des versions majeures v0 et v1 est obligatoire - et non facultative - afin qu'il existe un seul chemin d'importation canonique pour chaque package.

Pourquoi dois-je créer une nouvelle branche pour la v2 au lieu de continuer à travailler sur master ?

Vous n'avez pas besoin de créer une nouvelle branche. La publication des modules vgo donne malheureusement cette impression dans sa discussion sur la disposition du référentiel "branche majeure". Mais vgo ne se soucie pas des branches. Il recherche uniquement les balises et résout les commits spécifiques vers lesquels elles pointent. Si vous développez v1 sur master, vous décidez que vous avez complètement terminé avec v1, et que vous voulez commencer à faire des commits v2 sur master, c'est bien : commencez à baliser master avec des balises v2.xy. Mais notez que certains de vos utilisateurs continueront d'utiliser la v1 et vous souhaiterez peut-être parfois publier un correctif de bogue mineur v1. Vous voudrez peut-être au moins créer une nouvelle branche v1 pour ce travail au point où vous commencez à utiliser master pour v2.

La sélection minimale des versions n'empêchera-t-elle pas les développeurs d'obtenir des mises à jour importantes ?

C'est une peur courante, mais je pense vraiment que si quelque chose se produit, c'est le contraire qui se produira. Citant la section "Upgrade Speed" de https://research.swtch.com/vgo-mvs :

Étant donné que la sélection de version minimale prend la version minimale autorisée de chaque dépendance, il est facile de penser que cela conduirait à l'utilisation de très anciennes copies de packages, ce qui pourrait à son tour entraîner des bogues inutiles ou des problèmes de sécurité. En pratique, cependant, je pense que l'inverse se produira, car la version minimale autorisée est le maximum de toutes les contraintes, donc le seul levier de contrôle mis à la disposition de tous les modules d'une construction est la possibilité de forcer l'utilisation d'une version plus récente d'une dépendance que ce qui serait autrement utilisé. Je m'attends à ce que les utilisateurs d'une sélection de version minimale se retrouvent avec des programmes presque aussi à jour que leurs amis utilisant des systèmes plus agressifs comme Cargo.

Par exemple, supposons que vous écriviez un programme qui dépend d'une poignée d'autres modules, qui dépendent tous d'un module très courant, comme gopkg.in/yaml.v2. La construction de votre programme utilisera la dernière version de YAML parmi celles demandées par votre module et cette poignée de dépendances. Même une seule dépendance consciencieuse peut forcer votre build à mettre à jour de nombreuses autres dépendances. C'est l'opposé du problème du client Kubernetes Go que j'ai mentionné plus tôt.

Si quoi que ce soit, la sélection de version minimale souffrirait plutôt du problème opposé, à savoir que cette réponse «max des minimums» sert de cliquet qui force les dépendances à avancer trop rapidement. Mais je pense qu'en pratique, les dépendances avanceront à la bonne vitesse, ce qui finira par être juste ce qu'il faut de plus lent que Cargo et ses amis.

Par "bonne quantité plus lente", je faisais référence à la propriété clé selon laquelle les mises à niveau ne se produisent que lorsque vous les demandez, pas lorsque vous ne l'avez pas fait. Cela signifie que le code ne change (de manière potentiellement inattendue et cassante) que lorsque vous vous attendez à ce que cela se produise et que vous êtes prêt à le tester, à le déboguer, etc.

Voir aussi la réponse https://github.com/golang/go/issues/24301#issuecomment -375992900 par @Merovius.

Si $GOPATH est obsolète, où se trouve le code téléchargé ?

Le code que vous extrayez, travaillez et modifiez peut être stocké n'importe où dans votre système de fichiers, comme avec pratiquement tous les autres outils de développement.

Vgo a besoin d'espace pour contenir le code source téléchargé et installer les binaires, et pour cela, il utilise toujours $GOPATH, qui à partir de Go 1.9 est par défaut $HOME/go. Ainsi, les développeurs n'auront jamais besoin de définir $GOPATH à moins qu'ils ne souhaitent que ces fichiers se trouvent dans un répertoire différent. Pour changer uniquement l'emplacement d'installation du binaire, ils peuvent définir $GOBIN (comme toujours).

Pourquoi introduisez-vous le commentaire // import ?

N'étaient pas. C'était une convention préexistante . Le but de cet exemple dans la visite était de montrer comment go.mod peut déduire les bons chemins de module à partir des commentaires d'importation, s'ils existent. Une fois que tous les projets utilisent des fichiers go.mod , les commentaires d'importation seront complètement redondants et probablement obsolètes.

Résumé de la discussion (dernière mise à jour 2017-04-25)

Ce commentaire contient un résumé de la discussion ci-dessous.

Comment gérer la migration ?

[ https://github.com/golang/go/issues/24301#issuecomment -374739116 par @ChrisHines.]

Réponse https://github.com/golang/go/issues/24301#issuecomment -377529520 par @rsc. La proposition originale suppose que la migration est gérée par les auteurs qui se déplacent vers des sous-répertoires lorsque la compatibilité est importante pour eux, mais bien sûr, cette motivation est fausse. La compatibilité est le plus important pour les utilisateurs, qui ont peu d'influence sur le déplacement des auteurs. Et cela n'aide pas les anciennes versions. Le commentaire lié, maintenant également # 25069, propose une modification minimale de l'ancien "go build" pour pouvoir consommer et créer du code compatible avec les modules.

Comment gérer les enregistrements singleton ?

[ https://github.com/golang/go/issues/24301#issuecomment -374791885 par @jimmyfrasche.]

Réponse https://github.com/golang/go/issues/24301#issuecomment -377527249 par @rsc. Les collisions d'enregistrement de singleton (telles que http.Handle du même chemin) entre des modules complètement différents ne sont pas affectées par la proposition. Pour les collisions entre différentes versions majeures d'un même module, les auteurs peuvent écrire les différentes versions majeures à s'attendre à coordonner, généralement en faisant un appel v1 dans v2, puis utiliser un cycle d'exigences pour s'assurer que v2 n'est pas utilisé avec l'ancienne v1 qui ne Je ne sais pas pour la coordination.

Comment installer une commande versionnée ?

[ https://github.com/golang/go/issues/24301#issuecomment -375106068 par @leonklingele.]

Réponse https://github.com/golang/go/issues/24301#issuecomment -377417565 par @rsc. En bref, utilisez go get. Nous utilisons toujours $GOPATH/bin pour l'emplacement d'installation. N'oubliez pas que $GOPATH est désormais par défaut $HOME/go, donc les commandes se retrouveront dans $HOME/go/bin, et $GOBIN peut remplacer cela.

Pourquoi v0, v1 sont-ils omis dans les chemins d'importation ? Pourquoi les autres doivent-ils apparaître ? Pourquoi v0, v1 ne doivent jamais apparaître ?

[ https://github.com/golang/go/issues/24301#issuecomment -374818326 par @justinian.]
[ https://github.com/golang/go/issues/24301#issuecomment -374831822 par @jayschwa.]
[ https://github.com/golang/go/issues/24301#issuecomment -375437150 par @mrkanister.]
[ https://github.com/golang/go/issues/24301#issuecomment -376093912 par @mrkanister.]
[ https://github.com/golang/go/issues/24301#issuecomment -376135447 par @kaikuehne.]
[ https://github.com/golang/go/issues/24301#issuecomment -376141888 par @kaikuehne.]
[ https://github.com/golang/go/issues/24301#issuecomment -376213693 par @Merovius.]
[ https://github.com/golang/go/issues/24301#issuecomment -376247926 par @kaikuehne.]

Ajouté à la FAQ ci-dessus.

Pourquoi les fichiers zip sont-ils mentionnés dans la proposition ?

[ https://github.com/golang/go/issues/24301#issuecomment -374839409 par @nightlyone.]

L'écosystème gagnera à définir un format d'échange concret. Cela activera les proxys et autres outils. Dans le même temps, nous abandonnons l'utilisation directe du contrôle de version (voir justification en haut de cet article ). Ces deux motivations décrivent le format spécifique. La plupart des développeurs n'auront pas du tout besoin de penser aux fichiers zip ; aucun développeur n'aura besoin de regarder à l'intérieur, à moins qu'il ne construise quelque chose comme godoc.org.

Voir aussi #24057 à propos de zip vs tar.

Le fait de placer des versions majeures dans les chemins d'importation ne viole-t-il pas DRY ?

[ https://github.com/golang/go/issues/24301#issuecomment -374831822 par @jayschwa.]

Non, car la sémantique d'une importation doit être compréhensible sans référence au fichier go.mod. Le fichier go.mod ne spécifie que des détails plus fins. Consultez la seconde moitié de la section des versions d'importation sémantique de la proposition , en commençant par le guillemet bloc.

De plus, si vous séchez trop, vous vous retrouvez avec des systèmes fragiles. La redondance peut être une bonne chose. Donc "violer [ing] DRY" - c'est-à-dire se répéter limité - n'est pas toujours mauvais. Par exemple, nous mettons la clause package dans chaque fichier .go du répertoire, pas un seul. Cela a détecté des erreurs honnêtes dès le début et s'est ensuite transformé en un moyen facile de distinguer les packages de test externes (package x vs package x_test). Il y a un équilibre à trouver.

Quel fuseau horaire est utilisé pour l'horodatage dans les pseudo-versions ?

[ https://github.com/golang/go/issues/24301#issuecomment -374882685 par @tpng.]

UTC. Notez également que vous n'avez jamais à saisir vous-même une pseudo-version. Vous pouvez taper un hachage de validation git (ou un préfixe de hachage) et vgo calculera et substituera la pseudo-version appropriée.

Est-ce que vgo traitera les dépendances non-Go, comme C ou les tampons de protocole ? Code généré ?

[ https://github.com/golang/go/issues/24301#issuecomment -374907338 par @AlexRouSg.]
[ https://github.com/golang/go/issues/24301#issuecomment -376606788 par @stevvooe.]
[ https://github.com/golang/go/issues/24301#issuecomment -377186949 par @nim-nim.]

Le développement Non-Go continue d'être un non-objectif de la commande go , il n'y aura donc pas de support pour la gestion des bibliothèques C et autres, ni de support explicite pour les tampons de protocole.

Cela dit, nous comprenons certainement que l'utilisation de tampons de protocole avec Go est trop difficile, et nous aimerions que cela soit traité séparément.

En ce qui concerne le code généré plus généralement, un véritable système de construction inter-langage est la réponse, en particulier parce que nous ne voulons pas que chaque utilisateur ait besoin d'avoir les bons générateurs installés. Mieux vaut que l'auteur lance les générateurs et vérifie le résultat.

La sélection minimale des versions n'empêchera-t-elle pas les développeurs d'obtenir des mises à jour importantes ?

[ https://github.com/golang/go/issues/24301#issuecomment -375090551 par @TocarIP.]
[ https://github.com/golang/go/issues/24301#issuecomment -375985244 par @nim-nim.]
[ https://github.com/golang/go/issues/24301#issuecomment -375992900 par @Merovius.]

Ajouté à la FAQ.

### Puis-je utiliser master pour développer la v1 puis le réutiliser pour développer la v2 ?

[ https://github.com/golang/go/issues/24301#issuecomment -375248753 par @mrkanister.]
[ https://github.com/golang/go/issues/24301#issuecomment -375989173 par @aarondl.]

Oui. Ajouté à la FAQ.

Quel est le délai pour cela?

[ https://github.com/golang/go/issues/24301#issuecomment -375415904 par @flibustenet.]

Réponse dans https://github.com/golang/go/issues/24301#issuecomment -377413777 par @rsc. En bref, le but est de décrocher un "aperçu technologique" dans Go 1.11 ; les travaux peuvent se poursuivre quelques semaines après le gel, mais pas plus loin. N'envoyez probablement pas de PR ajoutant go.mod à chaque bibliothèque que vous pouvez trouver tant que la proposition n'est pas marquée comme acceptée et que la copie de développement de cmd/go a été mise à jour.

Comment puis-je effectuer une modification de sécurité incompatible avec les versions antérieures ?

[ https://github.com/golang/go/issues/24301#issuecomment -376236546 par @buro9.]

Réponse dans https://github.com/golang/go/issues/24301#issuecomment -377415652 par @rsc. En bref, les directives de compatibilité Go 1 autorisent les modifications avec rupture pour des raisons de sécurité afin d'éviter de heurter la version majeure, mais il est toujours préférable de le faire de manière à ce que le code existant fonctionne autant que possible. Par exemple, ne supprimez pas une fonction. Au lieu de cela, faites paniquer la fonction ou log.Fatal uniquement si elle est appelée de manière incorrecte.

Si un référentiel contient différents modules dans des sous-répertoires (par exemple, v2, v3, v4), vgo peut-il mélanger et faire correspondre différents commits ?

[ https://github.com/golang/go/issues/24301#issuecomment -376266648 par @jimmyfrasche.]
[ https://github.com/golang/go/issues/24301#issuecomment -376270750 par @AlexRouSg.]

Oui. Il traite chaque balise de version comme correspondant uniquement à un sous-arbre du référentiel global, et il peut utiliser une balise différente (et donc un commit différent) pour chaque décision.

Et si les projets abusaient de semver ? Devrions-nous autoriser les versions mineures dans les chemins d'importation ?

[ https://github.com/golang/go/issues/24301#issuecomment -376640804 par @pbx0.]
[ https://github.com/golang/go/issues/24301#issuecomment -376645212 par @powerman.]
[ https://github.com/golang/go/issues/24301#issuecomment -376650153 par @pbx0.]
[ https://github.com/golang/go/issues/24301#issuecomment -376660236 par @powerman.]

Comme le note @powerman , nous devons absolument fournir un vérificateur de cohérence de l'API afin que les projets puissent au moins savoir quand ils sont sur le point de publier un changement manifestement cassant.

Pouvez-vous déterminer si vous avez plusieurs packages dans une version ?

[ https://github.com/golang/go/issues/24301#issuecomment -376640804 par @pbx0.]

La chose la plus simple à faire serait d'utiliser goversion -m sur le binaire résultant. Nous devrions faire une option go pour montrer la même chose sans construire le binaire.

Préoccupations concernant la dépendance de vgo vis-à-vis du proxy par rapport au fournisseur, en particulier l'open source par rapport à l'entreprise.

[ https://github.com/golang/go/issues/24301#issuecomment -376925845 par @joeshaw.]
[ https://github.com/golang/go/issues/24301#issuecomment -376936614 par @kardianos.]
[ https://github.com/golang/go/issues/24301#issuecomment -376947621 par @Merovius.]
[ https://github.com/golang/go/issues/24301#issuecomment -376979054 par @joeshaw.]
[ https://github.com/golang/go/issues/24301#issuecomment -376988873 par @jamiethermo.]
[ https://github.com/golang/go/issues/24301#issuecomment -377134575 par @Merovius.]

Réponse : [ https://github.com/golang/go/issues/24301#issuecomment -377411175 by @rsc.] Le proxy et le fournisseur seront tous deux pris en charge. Le proxy est très important pour l'entreprise, et le fournisseur est très important pour l'open source. Nous voulons également construire un réseau miroir fiable, mais seulement une fois que vgo devient go.

Préoccupations concernant le protobuild en fonction de la sémantique GOPATH.

[ https://github.com/golang/go/issues/24301#issuecomment -377601170 par @stevvooe.]

Réponse [ https://github.com/golang/go/issues/24301#issuecomment -377602765 par @rsc] a demandé plus de détails dans un nouveau problème, mais ce problème ne semble pas avoir été classé.

Suggestion pour ajouter une balise spéciale vgo-v1-lock .

[ https://github.com/golang/go/issues/24301#issuecomment -377662150 par @kybin.]

Cela semble attrayant au début mais conduit à des cas particuliers qui ne valent probablement pas la peine d'être pris en charge. Réponse complète dans https://github.com/golang/go/issues/24301#issuecomment -384344659.

Comment patcher une dépendance profonde sans vendeur ?

[ https://github.com/golang/go/issues/24301#issuecomment -378255833 par @chirino.]

Réponse [ https://github.com/golang/go/issues/24301#issuecomment -378261916 par @kardianos.] En utilisant une directive de remplacement.

Que ferons-nous du changement de nom de module ?

[ https://github.com/golang/go/issues/24301#issuecomment -379020339 par @jimmyfrasche.]

Réponse [ https://github.com/golang/go/issues/24301#issuecomment -379307176 par @rsc.]
Ce sont des problèmes réels et préexistants que la proposition vgo ne tente pas de résoudre directement, mais il est clair que nous devrions éventuellement les résoudre. La réponse à la disparition du code est d'avoir des proxys de mise en cache (miroirs) avec une raison de leur faire confiance ; c'est un travail futur. (Ou utilisez le fournisseur dans le projet de niveau supérieur si vous préférez.) La réponse au déplacement de code est d'ajouter un concept explicite de redirection de module ou de package, tout comme les alias de type sont des redirections de type ; c'est aussi un travail futur.

Qu'en est-il de la connexion aux serveurs Git locaux ?

[ https://github.com/golang/go/issues/24301#issuecomment -383168012 par @korya.]

L'accès direct à git a été ajouté au plan. Voir #24915.

Qu'en est-il des packages binaires uniquement ?

[ https://github.com/golang/go/issues/24301#issuecomment -382793364 par @sdwarwick.]

Les packages binaires uniquement n'ont jamais été pris en charge que dans les circonstances limitées d'une sorte d'installation hors bande dans GOPATH/pkg. Go get n'a jamais pris en charge la récupération et l'installation d'un paquet binaire uniquement, et il continuera à ne pas le prendre en charge. Un package uniquement binaire ne fonctionne qu'avec un compilateur particulier et une copie particulière des dépendances, ce qui limite considérablement sa prise en charge. La bonne réponse est presque toujours d'utiliser le code source à la place.

Devrions-nous utiliser la syntaxe path@version dans le fichier go.mod ?

[ https://github.com/golang/go/issues/24301#issuecomment -382791513 par @sdwarwick.]

C'est le #24119. Cela semblait être une bonne idée au début, mais après mûre réflexion, non.

.

.

Le changement https://golang.org/cl/101678 mentionne ce problème : design: add 24301-versioned-go

Cette proposition est impressionnante et j'aime presque tout. Cependant, j'ai posté la préoccupation suivante sur la liste de diffusion, mais je n'ai jamais reçu de réponse. Entre-temps, j'ai vu ce problème soulevé par d'autres dans le canal mou de Gophers pour vgo et je n'y ai pas non plus vu de réponse satisfaisante.

De : https://groups.google.com/d/msg/golang-dev/Plc42fslQEk/rlfeNlazAgAJ

Je suis surtout préoccupé par le chemin de la migration entre un monde pré-vgo et un monde vgo qui tourne mal. Je pense que nous risquons d'infliger une douleur majeure à la communauté Go s'il n'y a pas un chemin de migration fluide. Il est clair que la migration ne peut pas être atomique dans toute la communauté, mais si j'ai bien compris tout ce que vous avez écrit sur vgo jusqu'à présent, il peut y avoir des situations où les packages largement utilisés existants ne seront pas utilisables à la fois par les outils pré-vgo et post -outils vgo.

Plus précisément, je pense que les packages existants qui ont déjà des versions étiquetées avec des versions majeures> = 2 ne fonctionneront pas avec vgo tant qu'ils n'auront pas un fichier go.mod et seront également importés avec un chemin d'importation augmenté /vN. Cependant, une fois ces modifications apportées au référentiel, cela interrompra les utilisations pré-vgo du package.

Cela semble créer un autre type de problème d'importation de diamants dans lequel les deux packages frères au milieu du diamant importent un package v2+ commun. Je crains que les packages frères doivent adopter les chemins d'importation vgo de manière atomique pour empêcher le package en haut du diamant d'être dans un état impossible à construire, qu'il utilise des outils vgo ou pré-vgo.

Je n'ai encore rien vu qui explique le chemin de migration dans ce scénario.

La proposition stipule :

Les builds compatibles avec les modules peuvent importer des packages non compatibles avec les modules (ceux en dehors d'un arbre avec un fichier go.mod) à condition qu'ils soient balisés avec une version sémantique v0 ou v1. Ils peuvent également faire référence à n'importe quel commit spécifique en utilisant une "pseudo-version" de la forme v0.0.0-yyyymmddhhmmss-commit. Le formulaire de pseudo-version permet de faire référence aux commits non étiquetés ainsi qu'aux commits qui sont étiquetés avec des versions sémantiques v2 ou supérieures mais qui ne suivent pas la convention de version d'importation sémantique.

Mais je ne vois pas de moyen pour les packages non compatibles avec les modules d'importer des packages compatibles avec les modules avec des dépendances transitives >= v2. Cela semble provoquer une fragmentation de l'écosystème d'une manière qui n'a pas encore été abordée. Une fois que vous avez une dépendance sensible au module qui a un package >= v2 quelque part dans ses dépendances transitives, cela semble forcer tous ses dépendants à adopter également vgo pour que la construction continue de fonctionner.

Mise à jour : voir aussi https://github.com/golang/go/issues/24454

Le projet Go a encouragé cette convention dès le début du projet, mais cette proposition lui donne plus de mordant : les mises à niveau par les utilisateurs de packages ne réussiront ou n'échoueront que dans la mesure où les auteurs de packages respectent la règle de compatibilité d'importation.

Je ne sais pas ce que cela signifie et comment cela change par rapport à la situation actuelle. Il me semble que cela décrit également la situation actuelle : si j'enfreins cette règle, les mises à niveau et le go-get échoueront. AIUI rien ne change vraiment et je suggérerais de supprimer au moins la mention "plus de dents". À moins, bien sûr, que ce paragraphe ne vise à impliquer qu'il existe des mécanismes supplémentaires en place pour pénaliser/empêcher les bris ?

Cela affecterait également des éléments tels que les pilotes de base de données et les formats d'image qui s'enregistrent avec un autre package lors de l'initialisation, car plusieurs versions majeures du même package peuvent finir par le faire. Je ne sais pas quelles en seraient toutes les répercussions.

Si la version majeure est v0 ou v1, alors l'élément de numéro de version doit être omis ; sinon, il doit être inclus.

Pourquoi est-ce? Dans le message lié, je ne vois que la justification selon laquelle c'est ce que les développeurs font actuellement pour créer des chemins alternatifs lorsqu'ils apportent des modifications avec rupture - mais c'est une solution de contournement pour le fait qu'ils ne prévoient pas initialement que l'outil ne gère pas les versions pour eux . Si nous passons à une nouvelle pratique, pourquoi ne pas autoriser et encourager (ou même imposer) que les nouveaux packages vgo incluent v0 ou v1 ? Il semble que les chemins sans versions ne soient que des opportunités de confusion. (Est-ce un package de style vgo ? Où est la limite du module ? etc.)

J'aime généralement la proposition, mais j'ai du mal à exiger des versions majeures dans les chemins d'importation :

  1. Cela viole le principe DRY lorsque la version majeure peut déjà être connue à partir du go.mod . Il est également difficile de comprendre ce qui se passera s'il y a un décalage entre les deux.
  2. L'irrégularité d'autoriser l'absence de v0 et v1 n'est pas non plus intuitive.
  3. Changer tous les chemins d'importation lors de la mise à niveau d'une dépendance semble potentiellement fastidieux.

Je comprends que des scénarios comme l'exemple moauth doivent être réalisables, mais j'espère que cela ne se fera pas au détriment de la simplicité des choses pour des scénarios plus courants.

Tout d'abord : un travail impressionnant !

Une chose qui m'est totalement obscure et qui me semble un peu sous-spécifiée :

Pourquoi y a-t-il un fichier zip dans cette proposition ?

La mise en page, les contraintes et les cas d'utilisation multiples comme le moment de sa création et la manière dont son cycle de vie est géré, les outils qui ont besoin d'être pris en charge, la manière dont des outils comme les linters doivent interagir avec lui ne sont pas non plus clairs, car ils ne sont pas couverts dans la proposition.

Je suggérerais donc soit de faire référence à une proposition ultérieure, encore non écrite, ici et de supprimer le mot zip, soit de supprimer toute la partie du texte de la proposition, si vous prévoyez de ne pas en discuter du tout dans le cadre de cette proposition.

En discuter plus tard permet également à différents publics de mieux contribuer ici.

Quel fuseau horaire est utilisé pour l'horodatage dans la pseudo-version (v0.0.0-yyyymmddhhmmss-commit) ?

Éditer:
Il est en UTC comme indiqué dans https://research.swtch.com/vgo-module.

@rsc Allez-vous traiter les dépendances C ?

On dirait que la sélection de version minimale rend la propagation des modifications sans rupture très lente. Supposons que nous ayons une bibliothèque populaire Foo, qui est utilisée par les projets A, B et C. Quelqu'un améliore les performances de Foo sans changer l'API. La réception actuelle des mises à jour est un processus de désinscription. Si le projet A a vendu Foo, mais que B et C ne l'ont pas fait, l'auteur n'a qu'à envoyer le pr avec la mise à jour de la dépendance du fournisseur à A. Ainsi, les contributions de rupture non API n'auront pas autant d'effet sur la communauté et sont quelque peu découragées par rapport à l'actuel. situation. C'est encore plus problématique pour les mises à jour de sécurité. Si un projet abandonné/petit/pas très actif (pas de bibliothèque) déclare une dépendance directe à l'ancienne version de x/crypto, par exemple, tous les utilisateurs de ce projet seront vulnérables aux failles de x/crypto jusqu'à ce que le projet soit mis à jour, potentiellement pour toujours. Actuellement, les utilisateurs de ces projets recevront la dernière version corrigée, ce qui aggrave la situation en matière de sécurité. L'IIRC a fait quelques suggestions pour résoudre ce problème dans la discussion sur la liste de diffusion, mais, pour autant que je sache, cette proposition ne le mentionne pas.

IIRC, il y a eu quelques suggestions sur la façon de réparer [l'obtention de correctifs de sécurité] dans la discussion sur la liste de diffusion, mais, pour autant que je sache, cette proposition ne le mentionne pas.

Voir la mention de go get -p .

Voir la mention de go get -p.

Je l'ai vu, mais c'est toujours un mécanisme opt-in.
Je pensais à un moyen pour la bibliothèque de marquer toutes les versions précédentes comme non sécurisées, de forcer l'utilisateur à exécuter go get -p ou à s'inscrire explicitement dans une bibliothèque non sécurisée.

Si la prise en charge de go get telle que nous la connaissons aujourd'hui est obsolète et éventuellement supprimée, quelle est alors la méthode recommandée pour récupérer et installer les fichiers binaires Go (non balisés) ? Nécessite-t-il d'abord git clone $ d'installer le projet, suivi d'un manuel go install pour installer le binaire ?
Si $GOPATH est obsolète, où ces binaires seront-ils installés ?

@leonklingele : d'après ce que j'ai compris, go get ne sera pas obsolète, au contraire.
Il sera amélioré avec des capacités de versioning automatiques et transparentes. Si un projet dépend d'un projet non étiqueté, il prendrait simplement le maître et le "vendeur" à cette version exacte.
Encore une fois, ma propre compréhension de la lecture d'un peu de vgo. Je suis encore en train de le comprendre complètement.

Je me demande comment cela affectera le flux de travail avec un référentiel Git en général, en s'appuyant également sur cette phrase de la proposition :

Si la version majeure est v0 ou v1, alors l'élément de numéro de version doit être omis ; sinon, il doit être inclus.

Pour le moment, il semble courant de travailler sur master (pour moi, cela inclut les branches de fonctionnalités de courte durée) et de baliser un commit avec une nouvelle version de temps en temps. J'ai l'impression que ce flux de travail est rendu plus déroutant avec les modules Go dès que je publie la v2 de ma bibliothèque, car j'ai maintenant une branche master et une branche v2 . Je m'attendrais à ce que master soit la branche actuelle et que v2 soit une branche de maintenance, mais c'est exactement l'inverse.

Je sais que la branche par défaut peut être modifiée de master à v2 , mais cela me laisse toujours la tâche de la mettre à jour chaque fois que je publie une nouvelle version majeure. Personnellement, je préférerais avoir une branche master et une branche v1 , mais je ne sais pas exactement comment cela cadrerait avec la proposition.

Les nouvelles versions majeures provoquent un désabonnement. Si vous devez modifier un paramètre dans votre référentiel Git (la branche par défaut) chaque fois que vous créez une nouvelle version, cela représente un coût très mineur par rapport au passage des utilisateurs de votre bibliothèque à la nouvelle version.

Je pense que cet aspect de la proposition constitue la bonne incitation : il encourage les auteurs en amont à réfléchir à la manière dont ils peuvent effectuer des changements de manière rétrocompatible, réduisant ainsi le désabonnement global de l'écosystème.

maintenant j'ai un master et une branche v2

Vous pouvez à la place créer un sous-répertoire v2/ dans master.

@mrkanister

Je préférerais avoir un maître et une branche v1, mais je ne sais pas exactement comment cela cadrerait avec la proposition.

Selon ma compréhension de https://research.swtch.com/vgo-module vgo utilise des balises et non des branches pour identifier les versions. Ainsi, vous pouvez continuer le développement sur master et brancher v1 tant que les balises pointent vers la branche et le commit corrects.

Les nouvelles versions majeures provoquent un désabonnement. Si vous devez modifier un paramètre dans votre référentiel Git (la branche par défaut) chaque fois que vous créez une nouvelle version, cela représente un coût très mineur par rapport au passage des utilisateurs de votre bibliothèque à la nouvelle version.

C'est un style de pensée problématique qui, je pense, a mordu Go dur dans le passé. Pour une personne sur un projet, changer la branche par défaut est simple pour le moment, oui. Mais aller à l'encontre des conventions de workflow signifiera que les gens oublient, surtout lorsqu'ils travaillent dans plusieurs langues. Et ce sera un autre exemple original de la façon dont Go fait les choses totalement différemment que les nouveaux arrivants doivent apprendre. Aller à l'encontre des conventions de flux de travail courantes des programmeurs n'est _pas du tout_ un coût mineur.

Aller à l'encontre des conventions de flux de travail courantes des programmeurs n'est pas du tout un coût mineur.

Ne pas suivre la voie conventionnelle est parfois la condition nécessaire à l'innovation.

Si j'ai bien compris certaines parties de la proposition, vous n'avez jamais besoin de créer un sous-répertoire ou une nouvelle branche. Vous pouvez potentiellement n'avoir qu'une branche master et une balise git pour votre référentiel de 0.0, à 1.0, à 2.0 et ainsi de suite tant que vous vous assurez de mettre à jour votre go.module vers le chemin d'importation correct pour votre bibliothèque.

@mrkanister Je pense que, pour dev, votre clone de votre maître (ou n'importe quelle branche dev) et utilisez la directive "replace" (voir vgo-tour) pour pointer dessus. (si je comprends ce que tu veux dire, pas sûr).

@rsc Je voudrais vous demander d'être plus précis sur la feuille de route et sur ce que nous devons faire maintenant.
Suivra-t-il la politique Go et le gel des fonctionnalités vgo à 3 mois (2 maintenant) ?
Devrions-nous maintenant aller avec notre bâton de pèlerin en demandant à chaque mainteneur de libs d'ajouter un fichier go.mod ou devrions-nous attendre que la proposition soit officiellement acceptée (pour être sûr que le nom et la syntaxe ne changeront pas) ?

Les outils @flibustenet ne sont pas couverts par la politique 1.0, donc tout peut changer.

https://golang.org/doc/go1compat

Enfin, la chaîne d'outils Go (compilateurs, éditeurs de liens, outils de construction, etc.) est en cours de développement actif et peut changer de comportement. Cela signifie, par exemple, que les scripts qui dépendent de l'emplacement et des propriétés des outils peuvent être interrompus par une version ponctuelle.

Aussi de la proposition

Le plan, sous réserve de l'approbation de la proposition, est de publier la prise en charge des modules dans Go 1.11 en tant que fonctionnalité facultative qui peut encore changer. La version Go 1.11 donnera aux utilisateurs la possibilité d'utiliser les modules "pour de vrai" et de fournir des commentaires critiques. Même si les détails peuvent changer, les futures versions pourront consommer des arborescences sources compatibles avec Go 1.11. Par exemple, Go 1.12 comprendra comment consommer la syntaxe du fichier Go 1.11 go.mod, même si d'ici là la syntaxe du fichier ou même le nom du fichier a changé. Dans une version ultérieure (par exemple, Go 1.12), nous déclarerons la prise en charge du module terminée. Dans une version ultérieure (par exemple, Go 1.13), nous mettrons fin à la prise en charge de go get des non-modules. La prise en charge du travail dans GOPATH se poursuivra indéfiniment.

Merci pour les commentaires.

@AlexRouSg

Selon ma compréhension de https://research.swtch.com/vgo-module vgo utilise des balises et non des branches pour identifier les versions. Ainsi, vous pouvez continuer le développement sur master et brancher v1 tant que les balises pointent vers la branche et le commit corrects.

Vous avez raison, cela continuera à fonctionner comme avant (juste revérifié pour être sûr), bonne prise !

Avec cela à l'écart, la chose que je (et apparemment d'autres) ne comprends pas est le raisonnement derrière l'interdiction d'un paquet v1 d'exister. J'ai essayé d'en importer un en utilisant /v1 à la fin de l'importation et en ajoutant également cela au go.mod du paquet importé, mais vgo cherchera un dossier nommé v1 la place.

@mrkanister
Je pense que la principale raison de ne pas autoriser v1 ou v0 dans le chemin d'importation est de s'assurer qu'il n'y a qu'un seul chemin d'importation pour chaque version compatible d'un package.
L'utilisation du chemin d'importation simple au lieu de /v1 facilite la transition, vous n'avez donc pas à mettre à jour tous vos chemins d'importation pour ajouter /v1 à la fin.

Salut,

Bien que de nombreux points de la proposition soient plus que bienvenus et aideront à apprivoiser les grandes bases de code Go qui ont émergé au fil du temps, la règle "utiliser la version minimale" est assez nuisible :

  • vous voulez que votre écosystème de code progresse. Cela signifie que vous voulez que les gens testent et utilisent les nouvelles versions et détectent les problèmes tôt avant qu'ils ne s'accumulent.
  • vous souhaitez que les nouvelles versions de modules, qui résolvent les problèmes de sécurité, soient appliquées dès que possible
  • vous voulez pouvoir appliquer les nouvelles versions de modules, qui résolvent les problèmes de sécurité, dès que possible. Ils ne sont pas toujours étiquetés aux correctifs de sécurité. Si vous évitez les nouvelles versions, vous évitez également ces correctifs
  • même lorsqu'une nouvelle version ne contient pas de correctifs de sécurité, l'application précoce de ses modifications signifie qu'il y aura moins de modifications à vérifier lors de la publication de la prochaine version contenant des correctifs de sécurité (et la dernière chose que vous voulez lorsqu'une telle version est publiée et que vous devez être rapide, c'est s'enliser dans des changements intermédiaires auxquels vous n'aviez pas pensé auparavant).
  • l'application de versions intermédiaires n'est nuisible que si elles cassent la compatibilité, et elles ne devraient pas casser la compatibilité, et si elles cassent la compatibilité, mieux vaut le détecter et en informer les auteurs du module avant qu'ils n'en fassent une habitude pour les prochaines versions, vous finirez par le faire absolument avoir besoin.
  • vous ne voulez pas que d'anciens morceaux de code vous entraînent vers le bas car ils spécifient toujours une ancienne version de dépendance et personne ne trouve le temps de mettre à jour son manifeste. L'utilisation de la dernière version d'une version majeure répond à ce besoin social dans d'autres écosystèmes de code : obliger les développeurs à tester la dernière version et à ne pas reporter jusqu'à ce qu'il soit trop tard car "il y a des choses plus importantes" (c'est-à-dire plus amusantes) à faire.

    • alors qu'en théorie, vous pouvez expédier un nombre illimité de versions de modules afin que chaque morceau de code puisse utiliser celui qu'il veut, en pratique dès que vous composez deux modules qui utilisent le même dep vous devez choisir une version donc plus votre logiciel est, moins vous tolérerez plusieurs versions. Alors vous vous heurtez bientôt au vieux problème de savoir quoi faire avec les retardataires qui ralentissent tout le convoi. Je n'ai jamais rencontré de culture humaine qui ait géré ce problème en disant aux traînards "tu as raison, va aussi lentement que tu veux, tout le monde t'attendra". C'est peut-être gentil et altruiste, mais ce n'est pas productif.

Combattre l'inertie humaine est dur et douloureux, et nous la combattons parce qu'elle est nécessaire pour progresser et non parce que c'est agréable. Fabriquer des outils agréables qui évitent le problème et incitent les humains à tergiverser davantage n'est d'aucune utilité, cela ne fera qu'accélérer la sédimentation des projets et l'accumulation de la dette technique. Il existe déjà des dizaines de projets Go sur github avec la plupart de leurs readme consacrés à l'auteur suppliant ses utilisateurs de mettre à jour car il a apporté des correctifs importants, le fait de choisir par défaut la version la plus ancienne généralisera le problème.

Une bonne règle serait "d'utiliser la dernière version qui correspond à la version majeure, pas chaque commit intermédiaire". Ce serait un compromis pour l'avenir et la stabilité. Il met le projet d'origine en commande, qui connaît le mieux la base de code, et peut décider sainement quand faire basculer ses utilisateurs vers un nouvel état de code.

Ma question sans réponse copiée de la liste de diffusion :

Nous nous attendons à ce que la plupart des développeurs préfèrent suivre la convention habituelle de "branche majeure", dans laquelle différentes versions majeures vivent dans différentes branches. Dans ce cas, le répertoire racine d'une branche v2 aurait un go.mod indiquant v2, comme ceci :

Il semble qu'il y ait des sous-répertoires et cette convention de branche majeure qui sont tous deux pris en charge par vgo. D'après mon expérience anecdotique, aucun dépôt ne suit cette convention en Go ou dans d'autres langages (je ne peux pas en penser un seul autre que ceux forcés par gopkg.in qui semble relativement inutilisé de nos jours). La branche principale est la dernière en date et possède des balises v2.3.4 dans son historique. Des balises existent pour tout séparer (pas seulement les versions mineures). S'il est nécessaire de corriger une ancienne version, une branche est temporairement créée à partir de la dernière balise v1, les commits poussés, une nouvelle balise poussée et la branche supprimée sommairement. Il n'y a pas de branche pour les versions, c'est juste les branches master/dev/feature actuelles + les balises de version. Je sais que "tout est une référence" dans Git, mais pour d'autres VCS, la distinction n'est peut-être pas aussi floue.

Cela dit, j'ai testé le flux de travail décrit ci-dessus avec vgo (juste avoir des balises qui disent v2.0.0, v2.0.1 et pas de branches) et cela semble fonctionner. Ma question est donc la suivante : bien que cela fonctionne maintenant, est-ce prévu ? Comme cela ne semble pas aussi bien décrit que les deux autres flux de travail du blog, et je veux m'assurer que travailler sans une branche v2/v3... n'est pas une fonctionnalité accidentelle qui disparaîtra puisque, comme je l'ai expliqué ci-dessus, je n'ai jamais vu ce flux de travail décrit (ou l'autre) dans le message pour être massivement adopté par n'importe qui (en particulier en dehors de la communauté Go).

Bien sûr, mon argument se résume à des préférences et à des anecdotes, donc je serais prêt à faire quelques grattages pour prouver cela dans toutes les langues si nécessaire. Jusqu'à présent, j'ai vraiment aimé les messages de proposition et je suis généralement d'accord avec les changements, je continuerai à suivre et à jouer avec vgo.

Merci pour tous vos efforts.

Quelqu'un peut-il peut-être clarifier comment le modèle alternatif proposé à MVS fonctionnerait pour améliorer la cadence de mise à niveau ? Parce que ce n'est pas clair pour moi. Ma compréhension du modèle alternatif (largement utilisé) est

  • Le développeur crée un manifeste artisanal, répertoriant les contraintes de version pour toutes les dépendances utilisées
  • Le développeur exécute $solver, qui crée un fichier de verrouillage, répertoriant un sous-ensemble choisi de versions de dépendance transitive qui satisfont aux contraintes spécifiées
  • Ce fichier de verrouillage est validé et est utilisé au moment de la construction et de l'installation pour garantir des constructions reproductibles
  • Lorsqu'une nouvelle version d'une dépendance est publiée et à utiliser, le développeur met potentiellement à jour le manifeste, réexécute le solveur et recommit le nouveau fichier de verrouillage

Le modèle MVS proposé tel que je le comprends est

  • Le développeur génère automatiquement go.mod , en fonction de l'ensemble des chemins d'importation dans le module, en sélectionnant la version la plus récente de toute dépendance transitive
  • go.mod est validé et est utilisé pour obtenir des limites inférieures sur les versions au moment de la construction et de l'installation. MVS garantit des builds reproductibles
  • Lorsqu'une nouvelle version d'une dépendance est publiée et doit être utilisée, le développeur exécute vgo get -u , qui récupère les versions les plus récentes des dépendances transitives et remplace go.mod par les nouvelles limites inférieures. Cela est ensuite soumis.

Il semble que je doive grossièrement oublier quelque chose et il serait utile que quelqu'un précise quoi. Parce que cette compréhension semble impliquer que les fichiers de verrouillage dus spécifient les versions exactes et celles utilisées dans la construction réelle, que MVS est meilleur pour augmenter la cadence de mise à niveau - car il ne permet pas de retenir les versions, en général.

Clairement, il me manque quelque chose (et je me sentirai stupide dans environ 5 minutes), qu'est-ce que c'est ?

@tpng

L'utilisation du chemin d'importation simple au lieu de /v1 facilite la transition, vous n'avez donc pas à mettre à jour tous vos chemins d'importation pour ajouter /v1 à la fin.

Cela ne devrait en fait pas être nécessaire. Laissez-moi vous donner un exemple:

Un utilisateur utilise actuellement par exemple v1.0.0 d'une bibliothèque, épinglée par un gestionnaire de dépendances et la balise dans le référentiel en amont. Maintenant, l'amont décide de créer un go.mod et appelle également le module /v1 . Cela devrait entraîner un nouveau commit et une nouvelle balise (par exemple v1.0.1 ). Étant donné que vgo n'essaiera jamais de mettre à jour les dépendances par lui-même, cela ne devrait rien casser pour l'utilisateur, mais il peut mettre à jour consciemment en modifiant également le chemin d'importation (pr vgo peut le faire pour lui/elle).

Je pense que la principale raison de ne pas autoriser v1 ou v0 dans le chemin d'importation est de s'assurer qu'il n'y a qu'un seul chemin d'importation pour chaque version compatible d'un package.

Oui, je suppose que je peux en effet voir ce point pour ne pas confondre les nouveaux utilisateurs d'une bibliothèque.

Si la version majeure est v0 ou v1, alors l'élément de numéro de version doit être omis ; sinon, il doit être inclus.

Quelqu'un peut-il s'il vous plaît expliquer le raisonnement derrière cela? Que dois-je faire, en tant qu'utilisateur d'une bibliothèque, lorsque je ne veux pas encore utiliser la v1, car elle a introduit un changement cassant, qui conviendrait parfaitement au versionnage sémantique (nouvelle version majeure) ?

Je préférerais n'omettre que la version antérieure à la version 1, ce qui indique un package instable/inachevé. À partir de la version 1, je veux pouvoir compter sur le fait que j'obtiens une version stable. Omettre la v1 dans le chemin d'importation est déroutant, car vous ne savez pas si vous suivez une bibliothèque en constante évolution ou une version stable. Je pense que cela ne fonctionne pas non plus bien avec le schéma de versionnage sémantique, où v1 identifie la première version stable, qui est utilisée pour distinguer clairement cette version des versions 0.x.

@kaikuehne

Que dois-je faire, en tant qu'utilisateur d'une bibliothèque, lorsque je ne veux pas encore utiliser la v1, car elle a introduit un changement cassant, qui conviendrait parfaitement au versionnage sémantique (nouvelle version majeure) ?

Pour autant que j'ai compris, vgo ne mettra jamais à jour les dépendances par lui-même, pas même vers une version de correctif, mais laissez plutôt cela comme une décision consciente que vous devez prendre. Donc, si vous dépendez de la v0.4.5 d'une bibliothèque (qui a une balise pour cela), vous pouvez théoriquement continuer à l'utiliser pour toujours. Vous pourrez également épingler la version manuellement dans votre fichier go.mod .

Que se passe-t-il si une autre dépendance que j'utilise dépend du même package, mais de la version v1 ? Les deux packages sont importés à l'aide du même chemin d'importation. N'y a-t-il pas un conflit lors de la compilation de ceux-ci dans le même binaire?

Si nous avions besoin que v1 fasse également partie du chemin d'importation, les deux seraient traités comme des packages différents, ce qu'ils sont en quelque sorte.

@kaikuehne alors il serait mis à jour vers la version commune minimale qui fonctionne. (à ma connaissance)

@kaikuehne Je ne comprends pas votre raisonnement. Vous utilisez v0, donc vous êtes probablement d'accord avec les changements de rupture ; pourquoi serait-ce un problème si la v1 tombe en panne, étant donné que vous utilisez déjà une version qui n'a aucune garantie de stabilité ? De plus, disons qu'au lieu de passer de v0.1-> v1.0 avec un changement avec rupture, en amont ajouterait la rupture à la v0.2 puis publierait une v1.0 (sans rupture). Cela semblerait bien correspondre aux attentes concernant les versions sémantiques, mais représenterait exactement la même quantité de travail pour vous (quel que soit le gestionnaire de packages utilisé). C'est-à-dire que je ne comprends vraiment pas comment "l'auteur a soudainement cessé de casser son API" constitue un problème qui n'est pas causé par l'utilisation d'une version antérieure à la 1.0.

En d'autres termes : en utilisant la v0.x, vous acceptez que la v0.(x+1) puisse vous obliger à corriger votre code. Pourquoi est-ce un problème si v0.(x+1) s'appelle plutôt v1.0 ?

Sur le point de discussion 4 : Adopter explicitement la règle de compatibilité d'importation et "le nouveau package doit être rétrocompatible avec l'ancien package"...

Dans mon cas, j'ai un package de sécurité https://github.com/microcosm-cc/bluemonday et j'ai récemment (à la fin de l'année dernière) eu un scénario dans lequel j'ai appris qu'une fonction publique n'était fondamentalement pas adaptée à l'usage. Je l'ai donc supprimé.

Selon cette proposition, si je supprimais la fonction, la version serait modifiée et le code non sécurisé/non sécurisé ne serait jamais supprimé.

Pour éviter cela, je préférerais probablement log.Fatal() dans la fonction que je souhaitais supprimer, uniquement pour m'assurer que le code existant n'utilise pas un point de terminaison non sécurisé, mais pour préserver la compatibilité.

Étant donné qu'aucun de ces éléments n'est idéal... comment pouvons-nous prévoir que les correctifs de sécurité qui nécessitent qu'une fonction publique soit strictement obsolète soient gérés ? (si ce n'est en surprenant le développeur avec un runtime log.Fatal() ?)

Pour ceux qui veulent voir le commit pour cela : https://github.com/microcosm-cc/bluemonday/commit/a5d7ef6b249a7c01e66856b585a359970f03502c

@Merovius Merci pour la clarification lors de l'utilisation des versions 0.x. Comme vous l'avez dit, il n'y a aucune garantie sur laquelle s'appuyer lors de l'utilisation d'une version antérieure à 1.0 et que les versions 0.x sont un cas particulier dans semver. Si j'ai bien compris, les règles décrites ne s'appliquent pas du tout aux versions 0.x. Ma question est simplement de savoir s'il serait logique de refléter également cette distinction dans le code, en particulier lors de la dénomination des packages. Par exemple, si un package n'importait que des packages sans version, vous pourriez voir en un coup d'œil qu'il est construit sur du code instable. Si toutes les importations contiennent une version v1, vous voyez qu'elle utilise des versions stables.

@buro9 La proposition suggère de suivre à peu près les garanties de compatibilité go1, qui contiennent des exemptions pour les ruptures d'API liées à la sécurité.

@kaikuehne Merci, cela clarifie votre préoccupation.

Il y a une interaction de fonctionnalités qui m'inquiète (en supposant que je comprenne bien les choses).

Si vous avez un module M qui utilise des versions réifiées (répertoires vN littéraux dans la source, pas des éléments de chemin d'importation synthétiques dérivés de balises), et que vous construisez un programme P qui s'appuie sur plusieurs versions majeures de M de manière transitive, n'est-ce pas devez-vous violer la sélection de version minimale dans certains scénarios ?

Autrement dit, disons que P dépend des versions majeures 2, 3 et 4 de M. Pour chaque version majeure de M, une version complète minimale est spécifiée. Étant donné que les versions de M partagent la source dans le but exprès de pouvoir faire des choses comme utiliser de manière transparente la même définition de type avec des alias de type, alors une seule copie de M peut être incluse pour les trois versions majeures au lieu d'une copie par version majeure. Tout choix de version complète pour une version majeure fixe le choix de la version complète des deux autres versions majeures et pourrait conduire à sélectionner une version non minimale pour l'une ou les deux autres versions majeures.

Comment vgo gère-t-il cela? Cela pourrait-il causer des problèmes autres que d'être parfois légèrement inférieur au minimum? (Comme s'il était possible de construire accidentellement un ensemble de modules qui ne donnent aucune solution ou qui font boucler le solveur ?)

@jimmyfrasche

Si vous utilisez des répertoires de versions majeures, vgo utilisera toujours des balises et n'obtiendra que le dossier de version correspondant à cette balise. par exemple, vous dépendez des versions 2, 3, 4. vgo vérifiera la balise v2.nm, v3.nm, v4.nm
Et puis à partir de la balise v2.nm, obtenez uniquement le dossier v2 et ainsi de suite. Donc, à la fin, tout suit toujours les balises.

J'ai posé une question dans ce message de la liste de diffusion , mais je n'ai pas vu de réponse concrète. Je le répète ici :

que se passera-t-il avec les ressources non-Go, telles que les fichiers protobufs ou c ? Toutes nos excuses si cela a déjà été répondu dans vos messages, mais nous utilisons le chemin du fournisseur pour distribuer et définir le chemin d'importation des fichiers protobuf. Bien que nous compilions les packages Go avec une sortie protobuf précompilée, nous devons également envisager le cas de la compilation de nouveaux packages Go à partir de fichiers protobuf dépendant des dépendances du fournisseur (c'est-à-dire des références rpc.Status à partir d'un autre fichier protobuf). Je peux fournir des exemples plus concrets si cette description est trop dense.

Plus précisément, j'ai un projet appelé protobuild qui permet de mapper l'importation de fichiers protobuf aux emplacements GOPATH. Je ne vois pas comment cette proposition gérera la résolution des ressources dans le GOPATH et comment nous pouvons mapper cela dans d'autres espaces d'importation de compilateur.

Travailler avec protobufs a été un énorme problème pour nous et ce projet a atténué bon nombre de ces problèmes. Il serait dommage que cela soit totalement incompatible avec la proposition.

Encore une fois, toutes mes excuses s'il y a quelque chose que j'ai raté.

J'adore la proposition. Je crains seulement que trop de projets introduisent fréquemment de petits changements avec rupture entre les versions mineures et réservent les changements de version majeurs uniquement pour les changements avec rupture très importants. Si des modifications mineures avec rupture de version sont fréquentes, des problèmes de dépendance au diamant se poseront car cela viole l'hypothèse de SIV. Je me demande si l'inclusion de la version mineure dans la déclaration d'importation aiderait davantage de projets à se conformer au contrat de modifications ininterrompues. Je pense que les inconvénients sont un roulement d'importation supplémentaire et que la mise à jour des versions mineures devient plus difficile (et plus explicite).

Cela soulève une autre question que j'ai : est-il facile (aujourd'hui) avec vgo de déterminer si vous avez plus d'une version d'un paquet dans une version ? Bien qu'il soit parfois crucial d'autoriser deux versions du même paquet pour aller de l'avant, il semble que la plupart des projets voudraient éviter cela à moins que cela ne soit temporaire en raison d'éventuels effets secondaires imprévus d'init. Avoir un moyen simple de vérifier cela peut être utile et certains projets peuvent vouloir l'appliquer lors de l'enregistrement du code.

Je crains seulement que trop de projets introduisent fréquemment de petits changements avec rupture entre les versions mineures et réservent les changements de version majeurs uniquement pour les changements avec rupture très importants.

Le changement de rupture est un changement de rupture. Il ne peut pas être petit ou grand. Je suppose que de tels paquets finiront par être rejetés par la communauté comme trop peu fiables et ne suivant pas semver. Même s'ils suivront semver et arriveront rapidement à un grand nombre majeur comme 42.xx, ils seront de toute façon très peu pratiques à utiliser. Donc, si vous voulez faire beaucoup de changements avec rupture, continuez à utiliser le numéro majeur 0. De cette façon, cela continuera à fonctionner comme go get actuel, avec les mêmes problèmes. Si vous souhaitez expérimenter l'API après avoir publié une version majeure non-0, déplacez ces expériences vers un package "expérimental" séparé avec un 0 majeur pour toujours et incrémentez le package principal principal lorsque vous avez terminé avec les "petits changements de rupture" et obtenez enfin la prochaine API stable.

L'inclusion de mineur dans le chemin d'importation viole l'idéologie semver et ne fournit aucune nouvelle fonctionnalité par rapport à l'inclusion de majeur.

Bien que je comprenne que c'est ce que les auteurs devraient faire compte tenu de la sémantique de semver, je crains que les modifications mineures parmi les versions mineures ne soient un cas courant et tentant pour quelqu'un qui a déjà dépassé la version 1. D'après mon expérience anecdotique, les auteurs de packages ne le font pas. suivez la sémantique exacte de semver et souvent les entreprises réservent les bosses des versions majeures à des fins de marketing. Donc, mon appel ne porte pas sur ce qui est idéal, mais sur s'il peut être pratique d'apporter certains changements pour mieux faire face à la réalité humaine désordonnée qui est semver.

Peut-être est-il même possible d'inclure éventuellement la version mineure pour les packages qui n'obéissent pas à semver, peut-être que cela bousille toute la proposition, j'aurais besoin d'y réfléchir davantage. Je ne propose pas que ce soit une meilleure façon seulement que je suis intéressé à explorer davantage les compromis de l'inclusion facultative ou de l'obligation d'inclure la version mineure dans les importations.

Il est probablement possible de générer de meilleures données ici à partir du corpus go (et d'un outil qui recherche les changements de rupture évidents) pour déterminer la fréquence à laquelle semver est, par exemple, principalement suivi parmi les projets populaires existants qui utilisent des balises semver.

La proposition vgo permet aux versions majeures de casser gracieusement les modifications de l'API. Il (par lui-même) ne fait rien pour les empêcher.

La proposition vgo permet à une version majeure de se référer à une autre version majeure, permettant une réutilisation gracieuse du code. Il ne fait rien pour forcer cela.

La proposition vgo MVS permet la mise à jour vers des packages plus récents. Cela ne vous oblige pas à mettre à jour.


Voici des choses que nous pouvons construire avec beaucoup plus de facilité dans un monde vgo :

  1. Outils pour intercepter les changements de freinage de l'API avant de pousser vers un hôte de module. Chaque version est dans un zip et peut être comparée sans de nombreux outils et commandes vcs différents.
  2. Registre des problèmes de sécurité. Hébergement parallèlement à l'hébergement de modules pour une valeur ajoutée. Les outils peuvent les interroger comme go list manuellement ou automatiquement et être informé des problèmes filtrés par une requête.

vgo les facilite en :

  • Contraindre l'espace du problème (travailler uniquement avec des fichiers zip, pas besoin de stocker l'historique git/hg/svn arbitraire pour faire des comparaisons d'API).

    • Définition de l'espace-problème (MVS, définition de version)

  • Outillage de la partie construction.

vgo fonctionne sur un principe principal : un seul ensemble d'entrées doit toujours générer la même chose. Si nous nous appuyons sur des reconstructions aléatoires pour intercepter les mises à jour de sécurité, nous le faisons mal . En tant que mainteneur de projets, certains projets Go s'exécutent pendant des années sans reconstruction. Je conviens que les mises à jour de sécurité en temps opportun sont importantes : vgo satisfait la partie construction de ce besoin.

Nous ne devrions pas confondre ce que vgo permet avec ce qu'est vgo.

@ pbx0 Je ne suis pas sûr que ce soit le bon endroit pour une telle discussion, peut-être que la liste de diffusion est plus appropriée. Dans tous les cas, des changements cassants sans changer le nombre majeur se produisent. Même occasionnellement. Semver a répondu à ce cas dans la FAQ :

Dès que vous vous rendez compte que vous avez enfreint la spécification Semantic Versioning, corrigez le problème et publiez une nouvelle version mineure qui corrige le problème et restaure la rétrocompatibilité.

Mais je pense qu'il y a là matière à amélioration. Je suppose qu'il devrait être assez facile d'implémenter un vérificateur d'API automatisé (peut-être même qu'il en existe déjà un), qui prendra tous les packages répertoriés sur godoc.org et vérifiera périodiquement les nouvelles versions, et au cas où une nouvelle version serait détectée, la nouvelle version serait compatible avec la précédente. l'API de la version au cas où elle utilise des balises semver et que la majeure n'a pas été modifiée. Essayez ensuite de contacter l'auteur en cas de modification incompatible détectée - peut-être des problèmes d'ouverture automatique sur github ou utilisez le courrier électronique du compte github. Cela ne couvrira pas tous les cas possibles, mais peut être très utile pour la communauté.

Je crois fermement à l'utilisation de chemins pour délimiter les versions majeures et je voulais exprimer mon soutien, FWIW.

Il y a un an, je pensais que mettre des versions dans des chemins d'importation comme celui-ci était moche, indésirable et probablement évitable. Mais au cours de la dernière année, j'ai compris à quel point ils apportent clarté et simplicité au système.

Il y a près de vingt ans, j'avais besoin d'un VCS pour ma startup et j'en ai essayé une dizaine de différents. J'ai immédiatement exclu Perforce car il exposait des branches à l'aide de répertoires. Ainsi, la branche v2 serait simplement le même code, mais sous un dossier v2. J'ai détesté cette idée. Mais après avoir exécuté des pilotes avec les neuf autres, j'ai découvert que je voulais souvent avoir les deux versions d'une branche sur mon système de fichiers local, et il s'est avéré que Perforce rendait cela trivialement facile alors que les autres le rendaient étonnamment compliqué. Le système de fichiers est notre métaphore de confinement. Utilisons-le.

De la proposition :

Définissez un schéma d'URL pour récupérer les modules Go à partir de proxys, utilisés à la fois pour installer des modules à l'aide de noms de domaine personnalisés et également lorsque la variable d'environnement $GOPROXY est définie. Ce dernier permet aux entreprises et aux particuliers d'envoyer toutes les demandes de téléchargement de modules via un proxy pour des raisons de sécurité, de disponibilité ou autres.

J'ai mentionné cela ailleurs, mais ma plus grande préoccupation avec la proposition est qu'elle semble écarter (ou du moins ne pas aborder) l'une des plus grandes forces du vendeur aujourd'hui : un code toujours disponible et des versions parfaitement reproductibles. Je ne pense pas que le système de proxy proposé réponde adéquatement à ces points forts ou ne les remplace pas.

Un projet qui utilise le fournisseur aujourd'hui ne nécessite que la chaîne d'outils Go et Git (ou un autre système de contrôle de version). Il n'existe qu'un seul point de défaillance : le dépôt git. Une fois le code vérifié, il peut être construit et reconstruit parfaitement sans avoir besoin de toucher à nouveau au réseau - une considération de sécurité importante. Pour la plupart d'entre nous, un projet de vente ne nécessite aucune infrastructure supplémentaire - juste votre ordinateur local et un compte GitHub gratuit.

La dépendance de vgo aux proxys introduit une surcharge d'infrastructure non triviale qui, à mon avis, n'est pas suffisamment soulignée. La nouvelle infrastructure doit être provisionnée, mise en œuvre, entretenue et surveillée. Cela peut être raisonnable pour les organisations de logiciels, mais c'est un fardeau pour les individus et les projets open source décentralisés. De plus, des choses comme CI sont souvent sous-traitées à des tiers comme Travis CI, qui ne fonctionnent pas dans la même infrastructure que l'environnement de développement de l'entreprise. Cela rend plus difficile la réutilisation de l'infrastructure proxy.

D'autres langages permettent l'utilisation de proxys de mise en cache. Python est celui avec lequel j'ai le plus d'expérience et, d'après mon expérience, il est rarement utilisé en raison des frais généraux liés à sa configuration. Peut-être que le projet Go peut rendre cela plus simple, mais si ce n'est pas la valeur par défaut, nous le trouverons utilisé moins souvent et la disponibilité des versions Go dans la nature diminuera considérablement. L'impact de l'événement NPM du pad gauche est une excellente étude de cas à cet égard.

Si le module et le système de proxy nous permettent de vérifier les dépendances à côté du code de notre propre projet (similaire au fournisseur aujourd'hui, mais pas nécessairement la même implémentation) et que l'implémentation du proxy vgo peut l'utiliser, cela répondrait à mes préoccupations. Mais si telle est l'intention, je pense qu'elle doit être abordée beaucoup plus en détail dans la proposition.

@joeshaw Vous pourrez continuer à utiliser un répertoire de fournisseurs pour créer une version autonome.

De la proposition :

Interdire l'utilisation des répertoires de fournisseurs, sauf dans une utilisation limitée : un répertoire de fournisseurs en haut de l'arborescence de fichiers du module de niveau supérieur en cours de construction est toujours appliqué à la construction, pour continuer à autoriser les référentiels d'applications autonomes. (Ignorer les répertoires des autres fournisseurs garantit que Go revient aux versions dans lesquelles chaque chemin d'importation a la même signification tout au long de la version et établit qu'une seule copie d'un package avec un chemin d'importation donné est utilisée dans une version donnée.)

Un projet qui utilise le fournisseur aujourd'hui ne nécessite que la chaîne d'outils Go et Git (ou un autre système de contrôle de version). Il n'existe qu'un seul point de défaillance : le dépôt git.

Aujourd'hui, si vous hébergez des packages sous votre propre domaine, vous devez a) héberger le référentiel git et b) servir les balises <meta> nécessaires pour le trouver. À l'avenir, vous devrez a) servir les fichiers .zip et .json nécessaires à vgo pour récupérer le code. Il semble y avoir moins de points de défaillance et moins d'infrastructure nécessaire pour l'hébergement pur. Bien sûr, vous devez toujours héberger le référentiel pour le développement, mais non seulement cela nous ramène au pire au même niveau qu'avant, mais le référentiel lui-même nécessite également un hébergement beaucoup moins évolutif et fiable, car il n'est utilisé que par des personnes qui développent réellement.

Ainsi, pour les importations de vanité, il ne semble pas y avoir beaucoup de différence en termes de frais généraux.

Si, OTOH, vous n'utilisez pas d'importations personnalisées, vous ne tenez pas compte de toute l'infrastructure que github exécute pour vous. Donc, cela ne semble pas être une comparaison de pommes à pommes : la seule façon de sortir vainqueur est de laisser les autres résoudre les problèmes difficiles. Mais rien ne vous empêche de le faire à l'avenir. AIUI Microsoft et d'autres se sont déjà portés volontaires pour investir des heures d'ingénierie et des capacités de service dans cette tâche. Je m'attends à ce qu'à l'avenir, l'effort d'hébergement de packages Go soit à peu près limité par l'effort d'hébergement de packages npm, de gemmes ou de caisses : vous avez un référentiel github, puis cliquez sur un bouton "rendre ceci disponible" sur certains service géré pour héberger les zips.

La dépendance de vgo aux proxys

Personnellement, je n'aime pas le mot "proxy" pour ce que fait l'infrastructure requise. "Miroir" semble plus approprié. Le miroir peut être implémenté en tant que proxy, mais il peut également s'agir d'un ensemble de fichiers servis par un serveur Web de votre choix, cachés derrière cloudflare pour une évolutivité et une disponibilité approximativement infinies.

D'autres langages permettent l'utilisation de proxys de mise en cache.

Je dirais que d'autres langues servent de modèle parfait pour expliquer pourquoi ce n'est pas vraiment un problème. Ils ont tendance à s'appuyer sur l'hébergement centralisé pour leurs packages pour héberger des packages - vgo ne supporte pas seulement ce modèle extrêmement bien, il le rend également facultatif (vous obtenez ainsi tous les avantages sans aucun des inconvénients) et très simple à mettre en œuvre, à dimensionner et à exploiter.


IMO, si vous comparez directement ce qui se passe avant et après et en Go et dans d'autres langues, il devrait être clair qu'il y a beaucoup d'équivalences 1:1. Et la seule raison pour laquelle il semble que cela demanderait plus d'efforts à l'avenir, c'est parce que nous prenons l'infrastructure existante pour acquise et constatons que la nouvelle infrastructure n'existe pas encore. Mais je ne pense pas que nous ayons de bonnes raisons de douter que ce sera le cas.

Ainsi, pour les importations de vanité, il ne semble pas y avoir beaucoup de différence en termes de frais généraux.

C'est vrai, mais la _vaste_ minorité de packages utilise des domaines personnalisés, donc je ne pense pas que ce soit un contrepoint fort. (J'ai également d'autres problèmes pratiques avec les domaines personnalisés, à savoir que leur disponibilité a tendance à être bien pire que la simple utilisation de GitHub.)

Si, OTOH, vous n'utilisez pas d'importations personnalisées, vous ne tenez pas compte de toute l'infrastructure que github exécute pour vous.

Oui, exactement! Je sens que cela fait mon point pour moi. Vous obtenez tout ce merveilleux travail sur l'infrastructure et le maintien de la disponibilité gratuitement ou à un coût raisonnable. Plus important encore, cela n'implique pas votre propre temps.

Si GitHub a fini par exécuter un miroir compatible vgo , alors c'est peut-être moins préoccupant, même si j'aime l'élégance d'une seule récupération Git - une action atomique du point de vue de l'utilisateur - contenant tout le code J'ai besoin de monter un projet.

Je dirais que d'autres langues servent de modèle parfait pour expliquer pourquoi ce n'est pas vraiment un problème. Ils ont tendance à s'appuyer sur l'hébergement centralisé pour leurs packages pour héberger des packages - vgo ne prend pas seulement très bien en charge ce modèle, il le rend également facultatif (vous bénéficiez donc de tous les avantages sans aucun des inconvénients) et très simple à mettre en œuvre, à mettre à l'échelle et fonctionner.

Le problème est que cela ajoute des points de défaillance uniques (SPOF) à la construction d'un projet. Le code va vivre dans un VCS quoi qu'il arrive (et probablement GitHub), donc c'est un SPOF. Dans d'autres langages, un référentiel centralisé est un deuxième SPOF. Pour Go, chaque chemin d'importation est un SPOF supplémentaire (github.com, golang.org, honnef.co, rsc.io, etc.) et l'augmentation des SPOF réduit la disponibilité globale.

L'exécution d'un miroir peut réduire ce nombre à deux, bien sûr, mais c'est une infrastructure qui, selon moi, n'a pas besoin d'exister. Vendre vos dépôts (ou avoir un miroir local sur disque) réduit cela à un seul : votre VCS.

Dans tous les cas, cela peut être un point discutable. Je n'ai pas compris à l'origine la partie de la proposition concernant le répertoire vendor niveau supérieur qui semblerait résoudre mes principales préoccupations - merci de l'avoir signalé, @kardianos - bien qu'une rupture nette avec l'ancien le système de vente pourrait être plus agréable.

Je suis content que "top-level vendor " soit toujours une configuration prise en charge car j'aime tellement git grep .

L'exécution d'un miroir peut réduire ce nombre à deux, bien sûr, mais c'est une infrastructure qui, selon moi, n'a pas besoin d'exister.

Développeur d'entreprise ici. Nous ne sommes peut-être pas le groupe démographique cible, mais nous aimerions utiliser Go. Je ne vois pas cela se produire sans que nous ayons un miroir à l'intérieur de notre entreprise, comme nous le faisons pour java et javascript, pour garantir que tout ce que nous construisons aujourd'hui peut être construit demain.

Développeur d'entreprise ici. Nous ne sommes peut-être pas le groupe démographique cible, mais nous aimerions utiliser Go. Je ne vois pas cela se produire sans que nous ayons un miroir à l'intérieur de notre entreprise, comme nous le faisons pour java et javascript, pour garantir que tout ce que nous construisons aujourd'hui peut être construit demain.

@jamiethermo La vente ne répond-elle pas à cela pour vous aujourd'hui ?

La prise en charge des proxys ou des miroirs est bonne, et si cela aide l'adoption de Go, je suis tout à fait d'accord. Ma préoccupation était que les miroirs remplacent les arborescences sources locales et autonomes (ce que nous appelons aujourd'hui la vente).

@joeshaw

Vending ne répond-il pas à cela pour vous aujourd'hui ?

Eh bien, je dois avouer mon ignorance et une certaine frustration avec "comment dois-je organiser mon code". Par "arborescence source autonome", voulez-vous dire que j'ai un référentiel git géant qui contient tout mon code, ainsi que tout le code de l'arborescence des fournisseurs ? Je n'ai donc pas besoin d'un miroir parce que j'ai vérifié tout ce code dans mon propre dépôt ?

En ce qui concerne "comment dois-je organiser mon code", cette page, How to Write Go Code , donne des instructions sur la structure des répertoires, mais ne fait aucune mention de la vente.

Adoptez la gestion sémantique des versions d'importation, dans laquelle chaque version majeure a un chemin d'importation distinct. Plus précisément, un chemin d'importation contient un chemin de module, un numéro de version et le chemin d'accès à un package spécifique à l'intérieur du module. Si la version majeure est v0 ou v1 , l'élément de numéro de version doit être omis ; sinon, il doit être inclus.

Les packages importés en tant que my/thing/sub/pkg , my/thing/v2/sub/pkg et my/thing/v3/sub/pkg proviennent des versions majeures v1 , v2 et v3 du module my/thing, mais la construction les traite simplement comme trois packages différents.

my/thing/sub/pkg peut aussi être v0.

J'ai suivi la tournée . L'exemple est construit en dehors de l'arborescence GOPATH, et cela fonctionne, alors que dep init barfs dans cette situation. Je travaille avec, je pense, 80 équipes maintenant, et ce serait vraiment bien de ne pas avoir à avoir un arbre géant. (Alors que je tapais ceci, quelqu'un s'est approché avec son ordinateur portable et un visage renfrogné, et "J'ai ce bogue vraiment bizarre...")

@joeshaw

Vous obtenez tout ce merveilleux travail sur l'infrastructure et le maintien de la disponibilité gratuitement ou à un coût raisonnable.

Je me suis mal exprimé. Je voulais dire "si vous prétendez que vous aviez besoin de moins d'infrastructure si vous n'utilisez pas d'importations personnalisées, vous ne tenez pas compte de toutes les infrastructures que github exécute pour vous". Je voulais souligner que l'infrastructure est toujours là et doit encore fonctionner. Et il peut continuer à être exécuté pour vous à l'avenir tout aussi bien.

Donc, votre préoccupation serait abordée dans ce que je considère comme le scénario le plus probable : qu'un organisme financé (actuellement Microsoft s'annonce comme ça) héberge les fichiers zip.

bien que j'aime l'élégance d'un seul Git fetch - une action atomique du point de vue de l'utilisateur

vgo get est tout autant une action atomique et elle fait moins de travail, de même nature (requêtes HTTP) plus facile à comprendre.

Le problème est que cela ajoute des points de défaillance uniques (SPOF) à la construction d'un projet.

Où est mon dernier commentaire incorrect, alors? Parce qu'il me semble assez évident que le nombre de points de défaillance est, au moins, inférieur , ils sont plus simples, plus faciles à mettre à l'échelle et moins chers à exploiter.

Dans d'autres langages, un référentiel centralisé est un deuxième SPOF. Pour Go, chaque chemin d'importation est un SPOF supplémentaire (github.com, golang.org, honnef.co, rsc.io, etc.) et l'augmentation des SPOF réduit la disponibilité globale.

Je pense que c'est trop simplifié. Si vous hébergez votre code sur un miroir qui tombe en panne, vous pouvez toujours développer (github est toujours en place) et les utilisateurs peuvent toujours être en mesure d'installer (en utilisant un miroir différent). L'hôte de l'une de vos dépendances qui tombe n'a pas d'importance, car vous reflétez vos dépendances. Si vous ne faites pas confiance au miroir "centralisé" géré par la communauté pour rester actif, vous pouvez exécuter le vôtre ou payer quelqu'un pour le faire, sans aucune différence pour les utilisateurs, vous donnant un contrôle total sur la façon dont vous êtes affecté par les temps d'arrêt de le dépôt centralisé.

Aucune des choses que vous mentionnez n'est en fait un SPOF, car vous obtenez toujours au moins un fonctionnement dégradé. Ajoutez à cela que les miroirs réels sont relativement simples à utiliser (car ce ne sont que des serveurs HTTP sans état) et je ne suis pas convaincu que la fiabilité et la disponibilité diminueraient de manière significative.

Et FTR, en ce moment votre git-hosting est un SPOF : si votre git-host est en panne, les utilisateurs ne peuvent pas installer et vous ne pouvez pas développer.

L'exécution d'un miroir peut réduire ce nombre à deux, bien sûr, mais c'est une infrastructure qui, selon moi, n'a pas besoin d'exister.

Et mon point (mal formulé) ci-dessus était que c'est déjà le cas :) Vous êtes simplement a) en ignorant que cela se produit en ce moment et b) en supposant que cela n'arrivera pas à l'avenir :)

Pour donner un autre point de vue :

  • nous construisons de nombreux projets Go avec notre gestionnaire de composants logiciels multilingues à l'échelle du système (rpm/dnf sur Fedora, Centos et RHEL)
  • cela nous permet d'utiliser les mêmes astuces que la proposition vgo, en jouant sur l'espace de noms du composant de la couche rpm (généralement, renommer un projet au niveau de l'espace de noms rpm de project à compat-project-x pour permettre de distinguer les versions incompatibles du même chemin d'importation, exactement comme vgo le fera).
  • ces astuces sont certainement utiles pour aider à construire des projets Go complexes
  • même si ce n'est pas aussi complet et robuste que de le faire au niveau de la langue
  • nous préférons relayer les contraintes de langage vers rpm/dnf plutôt que d'ajouter une superposition rpm/dnf de contraintes sur le code d'origine.
  • nous en avons assez de toutes les solutions de contournement du système de fichiers actuellement nécessaires pour convaincre les outils go de regarder les sources du projet Go. Le GOPATH physique ne nous manquera pas du tout.

Par conséquent, nous sommes ravis de vgo et espérons qu'il sera bientôt déployé (nous en avions besoin il y a des années).

Cela étant dit, notre utilisation de flux de travail de type vgo a exposé les difficultés suivantes.

La proposition vgo se félicite d'avoir rendu les makefiles inutiles. Ce n'est pas tout à fait vrai.

  • de nombreux projets Go sont tombés amoureux des fichiers go générés automatiquement et il n'y a pas de moyen standard d'exiger de les régénérer ou d'exprimer ce dont la génération a besoin pour réussir
  • c'est tellement grave que de nombreux projets doivent être livrés avec des fichiers prégénérés (constituant parfois des référentiels complets de fichiers prégénérés)
  • ces fichiers sont une énorme source d'incompatibilités de versions. Les humains prennent soin d'écrire du code qui n'aura pas besoin d'être modifié chaque jour lorsqu'il sera exposé à de nouvelles versions de dépendance. Les fichiers générés automatiquement OTOH sont souvent étroitement liés à un environnement de génération exact, car les auteurs d'outils générateurs supposent que vous les régénérerez simplement au besoin.
  • pour que vgo réussisse, il faut un moyen d'identifier ces fichiers, de les supprimer des modules .zip et d'expliquer comment les régénérer aux utilisateurs des modules .zip

Ceci est aggravé par la règle actuelle "tout doit être dans GOPATH"

  • tout ne peut pas être dans GOPATH quand la génération dépend de fichiers proto publiés hors GOPATH par des projets multi-langues
  • la chaîne d'outils Go doit apprendre à lire les ressources en dehors de son GOPATH
  • la chaîne d'outils Go doit apprendre à publier des ressources en dehors de GOPATH, lorsqu'elles sont exposées à des projets qui ne sont pas nécessairement écrits en Go
  • la solution actuelle de duplication des ressources dans les copies avec GOPATH est une autre source d'incompatibilités de version
  • tout le monde ne copiera pas les mêmes fichiers en même temps
  • parfois, les projets sont copiés à partir de plusieurs sources, créant des mélanges uniques.
  • chaque projet sera QA sur sa propre copie, ce qui rend la composition du projet Go dangereuse
  • le solveur de version vgo ne fonctionnera pas comme prévu s'il calcule les relations entre les versions de code mais ignore les relations entre les versions de ressources.
  • vgo doit rendre inutiles les copies privées des éléments publiés en dehors de GOPATH pour éviter une explosion de versions de modules incompatibles.

De nombreux projets ont exploité la règle "chaque répertoire Go est un package séparé" pour publier des projets avec du code incompatible ou complètement cassé dans des sous-répertoires séparés

  • de nombreux autres projets Go ont utilisé la même règle pour sélectionner des sous-répertoires spécifiques et les utiliser dans un contexte incompatible avec les tests unitaires et l'assurance qualité du projet d'origine
  • qui "fonctionne" et produit des "constructions reproductibles" tant qu'aucun changement dans le projet d'origine ou dans le consommateur du projet n'utilise une autre partie du projet d'origine. Lorsque cela se produit, tout le château de sable s'effondre sous la dette technique accumulée,
  • vous voyez des projets refuser de mettre à jour vers des versions de projet plus récentes car cela nécessite de nettoyer leurs précédentes utilisations abusives d'autres projets.
  • vous avez une schizophrénie étrange où les projets Go ne se considèrent pas responsables des bogues dans les bases de code qu'ils réutilisent, et en même temps refusent d'appliquer les correctifs publiés par ces mêmes bases de code (je suppose que nous sommes tous des humains et que le déni désagréable de la réalité est câblé dans le cerveau humain)
  • les correctifs ne se propagent pas, et tout va "bien" jusqu'à ce que vous trouviez les bogues qui nécessitaient les correctifs en premier lieu ou les tests unitaires qui ont été invalidés par la sélection.
  • un vérificateur de sécurité automatisé comparant l'état de sécurité des projets à l'état de sécurité des mêmes projets dans les répertoires du fournisseur aurait une journée sur le terrain
  • plus le projet est grand, plus il est probable que de telles bombes à retardement soient cachées à l'intérieur de ses distributeurs
  • en définissant clairement les limites du projet à l'intérieur des modules zip, vgo mettra fin à de telles pratiques
  • cependant, cela impliquera également un nettoyage majeur de nombreuses bases de code Go
  • pour que vgo réussisse, il doit fournir des outils pour aider les projets Go existants à refactoriser et diviser leur base de code en modules qui ont du sens du point de vue de la compatibilité logicielle. Sinon, les projets qui utilisent vgo produiront des contraintes inconciliables ou verrouilleront simplement le statu quo (ce qui fonctionne pour le code existant, mais est terrible du point de vue de l'évolution du code).

La pratique actuelle consistant à exposer l'ensemble de la base de code Go dans un seul arbre GOPATH avec peu de limites entre les projets a produit des effets secondaires délétères à partir d'un POW de génie logiciel.

  • le code n'est pas validé dans le projet où cela a un sens technique mais dans le référentiel le plus pratique pour l'auteur du code (le référentiel auquel il a accès)
  • Les projets Go saignent les uns sur les autres, avec des parties d'un projet dépendant de parties d'un autre projet, et une partie de cet autre projet dépendant du projet d'origine
  • qui produit affectivement des graphiques de contraintes de version verrouillée où vous ne pouvez pas déplacer une partie sans déplacer toutes les autres
  • personne n'a les ressources pour changer tous les autres en une seule opération
  • les projets se bloquent et ne progressent plus
  • utiliser des modules avec des limites claires et essayer de rendre explicites les contraintes de version inter-modules exposera ces situations
  • qui sera massivement impopulaire (même si le problème existe aujourd'hui, caché sous le voile de la vente)
  • bien souvent, il ne s'agit pas simplement de séparer un sous-répertoire : les dépendances de projet problématiques peuvent se produire dans une arborescence de répertoires A/B/C/D aux niveaux A et D, mais pas aux niveaux B et C.
  • pour que vgo réussisse, il doit fournir des outils pour aider les projets Go existants à refactoriser et diviser leurs bases de code en modules séparés qui suivent les lignes du graphique de dépendance

Testfing/fixtures, example et testdata sont une toute autre boîte de vers, avec leurs propres besoins de dépendance et de version de dépendance

  • ils doivent être isolés d'une manière ou d'une autre dans des modules séparés ou leurs besoins empoisonneront la résolution de la version du solveur
  • si vous ignorez leurs besoins, vous décidez effectivement que personne d'autre que le projet d'origine exécutera des tests unitaires
  • c'est assez dangereux lorsque vous autorisez les mises à niveau de version. Des problèmes vont arriver. Vous devez les détecter
  • les tests d'intégration qui dépendent non seulement d'un autre code, mais d'un environnement spécifique que personne d'autre que le projet d'origine ne peut répliquer (par exemple, un serveur ou un site Web spécifique auquel parler), nécessitent probablement une isolation spécifique

J'ai probablement oublié beaucoup plus de choses, mais ce sont les plus critiques.

Dernièrement:

  • Les projets Go ne vivent pas isolés
  • certains projets Go publient des connecteurs vers d'autres langages
  • certains projets dans d'autres langues publient des connecteurs Go
  • cela rend le traitement du semver différent de celui des autres langues, un problème.
  • vous ne pouvez pas tout avoir sauf la partie Go mise à jour vers la dernière version mineure lors de la sortie d'un projet multilingue.
  • ce serait l'enfer d'un prisonnier de guerre de gestion opérationnelle.
  • la mise à niveau automatique vers la dernière sous-version joue un rôle énorme dans la simplification des graphiques de contraintes logicielles en obligeant tout le monde à vider les anciennes versions (l'avantage est technique, le mécanisme est social).
  • les reconstructions haute fidélité sont similaires aux sites Web au pixel près. Ils ressemblent à une bonne idée, ils récompensent l'ego de l'auteur original, mais ils sont un PITA pour quiconque essaie réellement d'utiliser le résultat car ils ne sont pas évolutifs et adaptables au contexte local (non original).

Sur les serveurs proxy :

pour faciliter le débogage, $GOPROXY peut même être une URL file:/// pointant vers une arborescence locale.

Veuillez le faire fonctionner avec une URL file:/// de https:/// pointant vers un répertoire contenant des modules tiers sous forme de zip (et exclure tout le reste)

C'est le moyen le plus simple pour une entité de coordonner le travail de plusieurs équipes de développement qui s'appuient sur des sous-ensembles de la même liste de projets tiers : avoir une personne chargée de l'assurance qualité/juridique/sécurité chargée de vérifier les "bonnes" versions tierces et de les déployer dans un répertoire commun et que tout le monde fasse dépendre son travail des modules disponibles dans ce répertoire commun.

De cette façon, vous êtes sûr que personne ne commence à travailler sur un rev incompatible avec le travail des autres, et que personne ne reste sur un rev buggy ou dangereux déjà identifié par une autre équipe, et que vos stations de développement n'attendent pas en permanence le téléchargement des mêmes copies de logiciels déjà disponibles localement.

@Merovius Je ne suis pas d'accord, mais je pense que nous nous éloignons du sujet et que nous ne voulons pas enliser la discussion sur le problème. Je suis heureux de suivre dans un autre milieu, cependant. (Mon e-mail est dans mon profil github et je suis Joeshaw sur le mou Gophers.)

https://github.com/golang/go/issues/24301#issuecomment -374882685, @tpng :

Quel fuseau horaire est utilisé pour l'horodatage dans la pseudo-version (v0.0.0-yyyymmddhhmmss-commit) ?

Comme vous l'avez noté dans votre modification, UTC. Mais notez également que vous n'avez jamais à les taper. Vous pouvez simplement taper un hachage git commit (préfixe) et vgo calculera et substituera la pseudo-version correcte.

https://github.com/golang/go/issues/24301#issuecomment -374907338, @AlexRouSg :

Allez-vous traiter les dépendances C ?

https://github.com/golang/go/issues/24301#issuecomment -376606788, @stevvooe :

que se passera-t-il avec les ressources non-Go, telles que les fichiers protobufs ou c ?

https://github.com/golang/go/issues/24301#issuecomment -377186949, @nim-nim :

La proposition vgo se félicite d'avoir rendu les makefiles inutiles. Ce n'est pas tout à fait vrai. [Discussion du code généré.]

Le développement Non-Go continue d'être un non-objectif de la commande go , il n'y aura donc pas de support pour la gestion des bibliothèques C et autres, ni de support explicite pour les tampons de protocole.

Cela dit, nous comprenons certainement que l'utilisation de tampons de protocole avec Go est trop difficile, et nous aimerions que cela soit traité séparément.

En ce qui concerne le code généré plus généralement, un véritable système de construction inter-langage est la réponse, en particulier parce que nous ne voulons pas que chaque utilisateur ait besoin d'avoir les bons générateurs installés. Mieux vaut que l'auteur lance les générateurs et vérifie le résultat.

https://github.com/golang/go/issues/24301#issuecomment -375248753, @mrkanister :

Je sais que la branche par défaut peut être modifiée de master à v2, mais cela me laisse toujours la tâche de la mettre à jour chaque fois que je publie une nouvelle version majeure. Personnellement, je préférerais avoir un maître et une branche v1, mais je ne sais pas exactement comment cela cadrerait avec la proposition.

Comme @AlexRouSg et peut-être d'autres l'ont souligné, vous pouvez le faire. Je voulais juste confirmer leurs réponses. Je vais également l'ajouter à la FAQ.

https://github.com/golang/go/issues/24301#issuecomment -375989173, @aarondl :

Bien que cela fonctionne maintenant, est-ce prévu ?

Absolument oui.

@jamiethermo , merci beaucoup pour vos commentaires sur Perforce et ses branches dans différents répertoires. J'avais oublié cette fonctionnalité, mais c'est peut-être ce qui m'a convaincu qu'il était important de l'autoriser dans vgo.

Il y a eu une belle discussion à partir de https://github.com/golang/go/issues/24301#issuecomment -376925845 sur la vente par rapport aux proxys. Il y a clairement deux ensembles de préoccupations distinctes ici.

Les développeurs open source ont tendance à vouloir éviter de s'appuyer sur l'infrastructure, ils veulent donc vendre, comme l'a écrit @joeshaw . Pour confirmer, nous continuerons à le faire fonctionner, sous une forme limitée (uniquement le répertoire du fournisseur au niveau supérieur du module cible global où vous exécutez les commandes go).

Les développeurs d'entreprise n'ont aucun problème à s'appuyer sur l'infrastructure - c'est juste un autre coût - surtout si cela entraîne une réduction des coûts plus importante, comme ne pas dupliquer tout leur code fournisseur dans chaque dépôt et devoir passer du temps à tout synchroniser. Essentiellement, toutes les entreprises à qui nous avons parlé veulent des proxys/miroirs, pas des vendeurs, comme @jamiethermo l'a demandé. Nous veillerons également à ce que cela fonctionne.

Nous souhaitons également vivement construire un réseau de miroirs partagés auquel les développeurs ont des raisons de faire confiance et sur lequel ils peuvent compter, afin que tous les développeurs open source ne se sentent pas obligés de vendre. Mais c'est plus tard. Le premier vgo doit devenir go.

https://github.com/golang/go/issues/24301#issuecomment -377220411, @nim-nim :

Veuillez le faire fonctionner avec une URL file:/// de https:/// pointant vers un répertoire contenant des modules tiers sous forme de zip (et exclure tout le reste)

Je ne sais pas exactement ce que vous demandez en disant "exclure tout le reste". Si $GOPROXY est défini, vgo demande ce proxy. Il ne retombe jamais nulle part ailleurs. Ce proxy peut être servi par une arborescence de fichiers statique, qui est principalement constituée de modules tiers sous forme de zip. L'arborescence de fichiers doit également contenir d'autres fichiers de métadonnées, pour la navigation et la recherche. Ces fichiers supplémentaires sont inévitables, car HTTP ne nous donne pas un moyen standard de faire des choses comme les listes de répertoires.

https://github.com/golang/go/issues/24301#issuecomment -377186949, @nim-nim :

Wow, c'est un long commentaire. Je pense être d'accord avec la plupart de ce que vous avez écrit. Je veux répondre à la dernière puce de votre message :

  • les reconstructions haute fidélité sont similaires aux sites Web au pixel près. Ils ressemblent à une bonne idée, ils récompensent l'ego de l'auteur original, mais ils sont un PITA pour quiconque essaie réellement d'utiliser le résultat car ils ne sont pas évolutifs et adaptables au contexte local (non original).

Je pense que je dirais que les fichiers de verrouillage sont comme des sites Web au pixel près. Les constructions haute fidélité, en revanche, se dégradent avec élégance à mesure que le contexte change. Par défaut, une construction utilisera, disons, B 1.2 et C 1.4. Mais si cela fait partie d'une version plus large qui a besoin de B 1.3, très bien, il s'entendra avec B 1.3 mais conservera C 1.4 (même s'il en existe de plus récents) en l'absence d'une exigence concrète de mise à niveau. Ainsi, les constructions vraiment haute fidélité sont le meilleur des deux mondes : fidèles à l'original dans la mesure du possible, mais sans insister sur le pixel parfait lorsque ce n'est pas possible.

https://github.com/golang/go/issues/24301#issuecomment -375415904, @flibustenet :

@rsc Je voudrais vous demander d'être plus précis sur la feuille de route et sur ce que nous devons faire maintenant.
Suivra-t-il la politique Go et le gel des fonctionnalités vgo à 3 mois (2 maintenant) ?

Vgo est un prototype et ne sortira jamais seul. Il n'est pas soumis au gel ou à quoi que ce soit d'autre. Mais cette proposition consiste à déplacer les idées et la majeure partie du code dans le cmd/go principal. Dans le cadre de la version, cmd/go est certainement sujet au gel. Parce que c'est opt-in et parce que le code spécifique à vgo est assez bien isolé du reste du fonctionnement de la commande go, le travail sur des parties spécifiques à vgo présente un risque assez faible et je pourrais en voir un peu continuer pendant quelques semaines dans le gel. En ce moment, je me concentre sur la discussion de la proposition et les ajustements. Une fois que la proposition semble être en bon état sans problèmes importants, nous passerons au déplacement du code dans cmd/go.

Devrions-nous maintenant aller avec notre bâton de pèlerin en demandant à chaque mainteneur de libs d'ajouter un fichier go.mod ou devrions-nous attendre que la proposition soit officiellement acceptée (pour être sûr que le nom et la syntaxe ne changeront pas) ?

Je pense que la syntaxe go.mod est susceptible de changer (regardez ce numéro). Mais comme je l'ai noté dans la proposition, nous continuerons d'accepter les anciennes syntaxes pour toujours, et vgo mettra simplement à jour les fichiers existants, donc ce n'est pas énorme. Cela dit, je n'essaierais pas d'envoyer des PR à toutes les bibliothèques que vous pouvez trouver jusqu'à ce que le code atterrisse dans la copie de développement de cmd/go.

https://github.com/golang/go/issues/24301#issuecomment -376640804, @pbx0 :

est-il facile (aujourd'hui) avec vgo de déterminer si vous avez plus d'une version d'un paquet dans une version ?

La chose la plus simple à faire aujourd'hui est de construire le binaire, puis d'exécuter goversion -m dessus (voir https://research.swtch.com/vgo-repro). Lorsque nous avons une liste de choix plus générale prenant en compte les modules, elle devrait pouvoir faire la même chose sans d'abord créer le binaire.

https://github.com/golang/go/issues/24301#issuecomment -376236546, @buro9 :

[Puis-je apporter une modification de sécurité rétro-incompatible, comme microcosm-cc/ bluemonday@a5d7ef6 ? ]

Comme l'a dit @Merovius , si nous devons adopter les directives de compatibilité Go 1, les modifications de sécurité sont explicitement autorisées sans heurter la version majeure.

Cela dit, même lorsque vous devez faire quelque chose pour la sécurité, vous devriez probablement vous efforcer de minimiser les perturbations. Le commit auquel vous êtes lié est sans doute plus perturbateur que nécessaire, et dans une situation future, je vous encouragerais à aborder un tel changement du point de vue de "comment puis-je casser le moins de clients possible tout en éliminant le problème de sécurité ? "

Par exemple, ne supprimez pas une fonction. Au lieu de cela, faites paniquer la fonction ou log.Fatal uniquement si elle est appelée de manière incorrecte.

Dans ce cas, au lieu de supprimer AllowDocType, je l'aurais conservé et j'aurais certainement continué à accepter AllowDocType(false), car c'est le paramètre sécurisé. Si quelqu'un avait écrit un wrapper pour votre bibliothèque, peut-être en tant que programme de ligne de commande avec un indicateur -allowdoctype, alors au moins les utilisations du programme sans cet indicateur continueraient à fonctionner.

Et puis au-delà de cela, il semble que le souci était que le doctype était complètement décoché, mais j'aurais probablement mis en place une vérification minimale pour que les utilisations les plus courantes fonctionnent, puis j'en aurais rejeté les autres de manière conservatrice. Par exemple, au moins, j'aurais continué à autoriser et peut-être aussi pris la peine d'autoriser ..> avec des chaînes entre guillemets sans caractères &#<>\.

https://github.com/golang/go/issues/24301#issuecomment -375090551, @TocarIP :

[Inquiétude de ne pas recevoir les mises à jour rapidement.]

Je pense vraiment que le contraire se produira, que les programmes pourraient être plus à jour, car dans une sélection de version minimale, il est _impossible_ pour une dépendance d'empêcher la construction globale de se mettre à jour vers une version plus récente.

Ce que @Merovius a écrit dans https://github.com/golang/go/issues/24301#issuecomment -375992900 me semble tout à fait exact. Le point clé est que vous n'obtenez des mises à jour que lorsque vous les demandez, donc les choses (potentiellement) ne se cassent que lorsque vous vous y attendez et que vous êtes prêt à tester, déboguer, etc. Vous devez les demander, mais pas beaucoup plus souvent que dans d'autres systèmes avec des fichiers de verrouillage. Et nous souhaitons également faciliter la diffusion d'avertissements tels que "vous construisez avec une version obsolète/non sécurisée". Mais il est important de ne pas simplement mettre à jour silencieusement comme effet secondaire des opérations de non-mise à jour.

Également ajouté à la FAQ.

Merci à tous pour l'excellente discussion jusqu'à présent et pour avoir répondu aux questions des autres. De très bonnes réponses de beaucoup de gens, mais un merci spécial à @Merovius et @kardianos. J'ai mis à jour la FAQ https://github.com/golang/go/issues/24301#issuecomment -371228664 et le résumé de la discussion https://github.com/golang/go/issues/24301#issuecomment -371228742. Il y a trois questions importantes sans réponse (ils disent TODO dans le résumé), sur lesquelles je travaillerai ensuite. :-)

@rsc , # 24057 a une discussion sur l'utilisation de tar au lieu de zip.

https://github.com/golang/go/issues/24301#issuecomment -375106068, @leonklingele :

Si la prise en charge de go get telle que nous la connaissons aujourd'hui est obsolète et éventuellement supprimée, quelle est alors la méthode recommandée pour récupérer et installer les fichiers binaires Go (non balisés) ?

Ce sera toujours aller chercher. Si le référentiel du binaire n'est pas balisé, go get utilisera le dernier commit. Mais en réalité, les personnes qui publient des fichiers binaires devraient être encouragées à baliser les référentiels contenant de la même manière que les référentiels contenant des bibliothèques (ou un mélange).

Si $GOPATH est obsolète, où ces binaires seront-ils installés ?

Vous n'avez plus besoin de travailler dans $GOPATH, mais le code est toujours écrit dans le premier répertoire répertorié dans $GOPATH - c'est le cache source, voir $GOPATH/src/v après avoir utilisé vgo. Les binaires sont installés dans $GOPATH/bin. Depuis quelques versions, vous n'avez pas besoin de définir $GOPATH - il a une valeur par défaut, $HOME/go. Donc, ce qui devrait arriver, c'est que les développeurs cessent de se soucier de définir $GOPATH ou même de savoir ce que c'est, et ils apprennent simplement que leurs fichiers binaires sont dans $HOME/go/bin. Ils peuvent utiliser $GOBIN pour remplacer cet emplacement.

@dsnet , merci j'ai ajouté un lien dans le résumé de la discussion. Gardons cette discussion là-bas.

Si $GOPROXY est défini, vgo demande ce proxy. Il ne retombe jamais nulle part ailleurs. Ce proxy peut être servi par une arborescence de fichiers statique, qui est principalement constituée de modules tiers sous forme de zip. L'arborescence de fichiers doit également contenir d'autres fichiers de métadonnées, pour la navigation et la recherche. Ces fichiers supplémentaires sont inévitables, car HTTP ne nous donne pas un moyen standard de faire des choses comme les listes de répertoires.

Tant que les modules d'origine sont conservés sous forme de zip, éliminant toute tentation de les altérer, et que l'indexeur est robuste et léger, ça va.

Bien que les contraintes de liste ne s'appliquent pas aux fichiers et les utilitaires comme lftp ont pu lister les répertoires http depuis des lustres (peu importe si ce n'est pas standard si cela fonctionne sur les principaux serveurs http). Une opération sans indice est donc probablement possible et préférable pour les petites entités qui ne souhaitent pas investir dans l'infra. yum/dnf/zipper s'appuient également sur des index personnalisés et l'indexation d'un répertoire partagé n'est pas toujours aussi simple que vous pourriez le penser dans certaines organisations.

Les développeurs open source ont tendance à vouloir éviter de s'appuyer sur l'infrastructure, ils veulent donc vendre, comme l'a écrit @joeshaw

Pas vraiment, les développeurs open source veulent surtout que l'ensemble du processus soit ouvert et transparent, et qu'ils n'aient pas à compter sur les bons souhaits de quelqu'un d'autre. Donc, infra est parfaitement bien tant qu'il est lui-même open source et facile et peu coûteux à déployer localement. S'appuyer sur d'énormes sites propriétaires de boîtes noires comme github n'entre clairement pas dans cette catégorie, mais ce n'est pas la même chose qu'infra. Les gens de l'open source ont fait des miroirs des décennies avant tout le monde. Ce qu'ils n'accepteront pas, ce sont des miroirs fermés et coûteux à mettre en place (en termes open source, coûteux se mesure en temps humain)

La nature ouverte, facile et bon marché de la vente est appréciée, le processus de vente lui-même et la façon dont il encourage la fossilisation progressive des bases de code sur des versions obsolètes de code tiers, pas tellement.

Les développeurs d'entreprise n'ont aucun problème à s'appuyer sur l'infrastructure - c'est juste un autre coût

Ce doit être tellement agréable de travailler chez Google :(. À l'exception du petit nombre d'entreprises ayant une grande opération Go existante où investir dans Go infra est une évidence, tout le monde devra passer par des processus d'approbation longs et fastidieux , ne serait-ce que pour justifier de payer quelqu'un pour étudier le problème.Ainsi, tout coût d'infra réduira la portée du Go et empêchera son adoption par de nouvelles structures.

Les entreprises sont comme les opensources, elles se soucient du bon marché et de la facilité. Auparavant, ils ne se souciaient pas du tout de l'ouverture, mais cela change lentement maintenant qu'ils réalisent que cela est en corrélation avec le bon marché (au grand désarroi des fournisseurs d'entreprise traditionnels qui se spécialisaient dans les solutions de boîte noire coûteuses avec des conseils coûteux pour aider les déploiements).

Les entreprises qui sous-traitent l'informatique interne au plus bas soumissionnaire insisteront définitivement sur les miroirs car elles ne veulent certainement pas que leurs développeurs bon marché téléchargent du code défectueux ou dangereux que les développeurs ne comprennent pas sur Internet. Ils paieront des humains et des outils pour analyser le contenu du miroir local à la recherche de problèmes et forceront l'informatique interne à l'utiliser exclusivement.

Nous souhaitons également vivement construire un réseau de miroirs partagés auquel les développeurs ont des raisons de faire confiance et sur lequel ils peuvent compter, afin que tous les développeurs open source ne se sentent pas obligés de vendre.

Publiez simplement une copie de référence d'un répertoire indexé contenant des modules quelque part. Oubliez toute configuration de type proxy qui nécessite une configuration de serveur Web spécifique. C'est ce que font les open sources et ils n'ont aucune difficulté à se faire refléter. Tant que la mise en miroir consiste simplement à copier le contenu d'un répertoire et ne nécessite pas de configuration de serveur Web spécifique, de nombreuses organisations sont prêtes à mettre en miroir.

En ce qui concerne le code généré plus généralement, un véritable système de construction inter-langage est la réponse,

Vous savez aussi bien que moi que cela n'arrivera jamais, quelqu'un voudra toujours inventer un nouveau langage qui fait ses propres trucs. C'est un argument d'homme de paille.

Cela n'empêche pas Go de normaliser une commande standard qui lance le processus spécifique au projet qui génère le code, avec des directives strictes sur ce qu'il peut et ne peut pas faire (généralement, il ne devrait rien faire déjà couvert par les commandes Go standard, car ces commandes devraient être déjà bien tel quel).

spécifiquement parce que nous ne voulons pas que chaque utilisateur ait besoin d'avoir les bons générateurs installés. Mieux vaut que l'auteur lance les générateurs et vérifie le résultat.

Cela nécessiterait une refonte majeure de la manière dont les générateurs existants sont implémentés, car pour le moment, ils ne se soucient pas du tout de la portabilité des versions et s'attendent à ce que l'environnement logiciel soit gelé avant la génération. Avec pour effet direct que la génération rend tout changement de version ultérieur sans régénération dangereux. Peu importe si le résultat est vérifié par des humains ou non, car les humains ne vérifieront que par rapport à l'ensemble de versions d'origine. vgo s'appuie sur la possibilité d'effectuer des modifications de version ultérieures.

Vgo devra donc s'attaquer tôt ou tard à la régénération. Plus tard signifie attendre que les projets découvrent que les mises à jour vgo sont dangereuses en présence de code généré.

https://github.com/golang/go/issues/24301#issuecomment -374791885, @jimmyfrasche :

Cela affecterait également des éléments tels que les pilotes de base de données et les formats d'image qui s'enregistrent avec un autre package lors de l'initialisation, car plusieurs versions majeures du même package peuvent finir par le faire. Je ne sais pas quelles en seraient toutes les répercussions.

Oui, le problème du code qui suppose "qu'il n'y en aura qu'un seul dans un programme" est réel, et c'est quelque chose que nous allons tous devoir résoudre pour établir de nouvelles (meilleures) meilleures pratiques et conventions. Je ne pense pas que ce problème soit introduit par vgo, et vgo rend sans doute la situation meilleure qu'avant.

Je comprends que certaines personnes soutiennent que vgo devrait adopter la règle de Dep selon laquelle il ne peut même pas y avoir de 1.x et 2.x ensemble, mais cela ne correspond très clairement pas aux grandes bases de code que nous ciblons avec Go. Il est impossible de s'attendre à ce que de grands programmes entiers passent d'une API à une autre en une seule fois, comme le montre le message vgo-import . Je pense que tous les autres gestionnaires de packages autorisent 1.x et 2.x ensemble pour la même raison. Certainement Cargo le fait.

En général, vgo réduit la duplication par rapport à la vente. Avec la vente, il est facile de se retrouver avec 1.2, 1.3 et 1.4 d'un paquet donné dans un seul binaire, sans s'en rendre compte, ou peut-être même trois copies de 1.2. Au moins vgo réduit la duplication possible à un 1.x, un 2.x, et ainsi de suite.

C'est déjà le cas que les auteurs de différents packages doivent s'assurer de ne pas essayer d'enregistrer la même chose. Par exemple, expvar fait http.Handle("/debug/vars") et a essentiellement revendiqué ce chemin. J'espère que nous sommes tous d'accord sur le fait qu'un package tiers comme awesome.io/supervars ne devrait pas tenter d'enregistrer le même chemin. Cela laisse des conflits entre plusieurs versions d'un même package.

Si nous introduisons expvar/v2, cela finit par être un deuxième package différent, tout comme awesome.io/supervars, et cela peut entrer en conflit avec expvar dans une grande construction. Contrairement aux supervars, cependant, expvar/v2 appartient à la même personne ou équipe que expvar, de sorte que les deux packages peuvent se coordonner pour partager l'enregistrement. Cela fonctionnerait comme suit. Supposons que expvar v1.5.0 soit la dernière avant que nous décidions d'écrire v2, donc v1.5.0 contient un http.Handle. Nous voulons que la v2 remplace la v1, nous allons donc déplacer le http.Handle vers la v2.0.0 et ajouter une API dans la v2 qui permet à la v1 de transférer ses appels vers la v2. Ensuite, nous créerons la v1.6.0 qui est implémentée avec cette redirection. v1.6.0 n'appelle pas http.Handle ; il délègue cela à v2.0.0. Maintenant, expvar v1.6.0 et expvar/v2 peuvent coexister, car nous l'avons prévu de cette façon. Le seul problème qui reste est que se passe-t-il si une construction utilise expvar v1.5.0 avec expvar/v2 ? Nous devons nous assurer que cela n'arrive pas. Nous le faisons en faisant en sorte que expvar/v2 nécessite expvar à la v1.6.0 (ou ultérieure), même s'il n'y a pas d'importation dans cette direction, et bien sûr expvar v1.6.0 nécessite également expvar/v2 à la v2.0.0 ou ultérieure pour appeler ses API . Ce cycle d'exigences nous permet de nous assurer que la v1.5.0 et la v2 ne sont jamais mélangées. La planification de ce type de coordination inter-versions majeures est exactement la raison pour laquelle la sélection de version minimale permet des cycles dans le graphique des exigences.

La règle "une seule version majeure" combinée à l'autorisation de cycles dans le graphe des exigences donne aux auteurs les outils dont ils ont besoin pour gérer la bonne coordination des singletons (et la migration de la propriété des singletons) entre les différentes versions majeures de leurs modules. Nous ne pouvons pas éliminer le problème, mais nous pouvons donner aux auteurs les outils dont ils ont besoin pour le résoudre.

Je sais que les tampons de protocole en particulier ont des problèmes d'enregistrement, et ces problèmes sont exacerbés par la manière très ad hoc dont les fichiers de protocole .pb.go sont transmis et copiés dans les projets. C'est encore quelque chose qui est principalement indépendant de vgo. Nous devrions le corriger, mais probablement en modifiant la façon dont les tampons du protocole Go sont utilisés, pas vgo.

https://github.com/golang/go/issues/24301#issuecomment -374739116, @ChrisHines :

Je suis surtout préoccupé par le chemin de la migration entre un monde pré-vgo et un monde vgo qui tourne mal. [plus de détails]

Je suis vraiment heureux que ce soit le tout premier commentaire sur la proposition. C'est clairement la chose la plus importante à faire correctement.

La transition de l'ancien go get et de la myriade d'outils de vente vers le nouveau système de modules doit se dérouler de manière incroyablement fluide. J'ai beaucoup réfléchi récemment à la manière exacte dont cela fonctionnera.

La proposition originale offre aux développeurs la possibilité de placer la version 2 d'un module dans un sous-répertoire repo nommé v2/. L'exercice de cette option permettrait aux développeurs de créer un référentiel qui utilise la gestion des versions d'importation sémantique, est compatible avec les modules, et pourtant est également rétrocompatible avec l'ancien "go get". Le post décrivant cette option admet que la grande majorité des projets ne voudront pas exercer cette option, ce qui est bien. Il n'est nécessaire pour la compatibilité que si un projet est déjà à la version 2 ou ultérieure. Dans le même temps, j'ai sous-estimé le nombre de grands projets largement utilisés qui sont à la version 2 ou ultérieure. Par example:

  • github.com/godbus/dbus est à la v4.1.0 (importé par 462 packages).
  • github.com/coreos/etcd/clientv3 est à la v3.3.3 (importé par 799 packages).
  • k8s.io/client-go/kubernetes est à la v6.0.0 (importé par les packages 1928).

Pour éviter de casser leurs clients, ces projets devraient se déplacer vers un sous-répertoire jusqu'à ce que tous les clients puissent être supposés utiliser des modules, puis remonter à la racine. C'est beaucoup demander.

Une autre option pour jouer un tour avec les sous-modules git. L'ancienne commande go get préfère une balise ou une branche nommée "go1" à la branche par défaut du dépôt, donc un projet qui voulait permettre une transition en douceur pourrait créer un commit sur une branche "go1" qui n'avait qu'un sous-répertoire "v2" configuré en tant que sous-module git pointant vers la véritable racine du dépôt. Lorsque "go get" extrait cette branche go1 et les sous-modules remplis, il obtient la bonne disposition de l'arborescence de fichiers. C'est un peu horrible, cependant, et les pointeurs de sous-module devraient être mis à jour à chaque fois qu'une nouvelle version est publiée.

Ces deux éléments ont pour effet malheureux que les auteurs doivent prendre des mesures pour éviter de casser leurs utilisateurs, et même dans ce cas uniquement pour les nouvelles versions. Nous aimerions plutôt que le code des utilisateurs continue de fonctionner même sans travail supplémentaire de la part des auteurs, et idéalement même pour les anciennes versions.

Mais ce sont les seuls moyens auxquels je peux penser pour continuer à travailler sans modification pendant que nous passons au monde des modules. Si ce n'est pas ceux-là, alors l'alternative est de modifier l'ancien go get, ce qui signifie vraiment modifier l'ancien go build.

Fondamentalement, il existe deux conventions de chemin d'importation différentes : l'ancienne, sans versions majeures, et la nouvelle, avec des versions majeures v2 ou ultérieures. Le code d'un ancien arbre utilise probablement l'ancienne convention, tandis que le code d'un nouvel arbre - sous un répertoire contenant un fichier go.mod - utilise probablement la nouvelle convention. Nous avons besoin d'un moyen de faire se chevaucher les deux conventions lors d'une transition. Si nous enseignons aux anciens comment obtenir une petite quantité de versions d'importation sémantique, nous pouvons augmenter considérablement la quantité de chevauchement.


Modification proposée : Définissez le "nouveau" code comme code avec un fichier go.mod dans le même répertoire ou un répertoire parent. L'ancien Go Get doit continuer à télécharger le code exactement comme il l'a toujours fait. Je propose que l'étape "go build" ajuste sa gestion des importations dans le "nouveau" code. Plus précisément, si une importation dans un nouveau code indique x/y/v2/z mais que x/y/v2/z n'existe pas et que x/y/go.mod indique "module x/y/v2", alors go build lira l'importation en tant que x/y/z à la place. Nous pousserions cette mise à jour en tant que version intermédiaire pour Go 1.9 et Go 1.10.

Mise à jour : Copié vers #25069.


Ce changement devrait permettre aux packages non compatibles avec les modules d'utiliser des versions plus récentes de packages compatibles avec les modules, que ces packages choisissent l'approche "branche principale" ou "sous-répertoire principal" pour structurer leurs référentiels. Ils ne seraient plus contraints à l'approche sous-répertoire, mais ce serait toujours une option de travail. Et les développeurs utilisant des versions plus anciennes de Go pourraient toujours créer le code (au moins après la mise à jour vers la version intermédiaire).

@rsc J'ai essayé de comprendre comment nous pourrions également faire fonctionner la transition vers vgo, je suis arrivé aux mêmes conclusions que vous avez énoncées dans votre réponse et votre suggestion correspond à la meilleure approche que j'ai trouvée me débrouiller tout seul. J'aime votre proposition de changement.

https://github.com/golang/go/issues/24301#issuecomment -377527249, @rsc :

Ensuite, nous créerons la v1.6.0 qui est implémentée avec cette redirection. v1.6.0 n'appelle pas http.Handle ; il délègue cela à v2.0.0. Maintenant, expvar v1.6.0 et expvar/v2 peuvent coexister, car nous l'avons prévu de cette façon.

Cela semble plus facile qu'il ne l'est. En réalité, dans la plupart des cas, cela signifie que la v1.6.0 doit être une réécriture complète de la v1 sous la forme d'un wrapper v2 _ (l'appel transféré à http.Handle entraînera l'enregistrement d'un autre gestionnaire - un de la v2 - ce qui signifie à son tour tous les le code doit également provenir de la v2 pour interagir correctement avec le gestionnaire enregistré)_.

Cela modifiera très probablement des détails subtils sur le comportement de la v1, en particulier avec le temps, à mesure que la v2 évolue. Même si nous serons en mesure de compenser ces changements de détails subtils et d'émuler assez bien la v1 dans la v1.6.x - cela représente tout de même beaucoup de travail supplémentaire et rend très probablement le support futur de la branche v1 (je veux dire les successeurs de la v1.5.0 ici) sans signification.

@powerman , je ne dis absolument pas que c'est trivial. Et vous n'avez besoin de vous coordonner que dans la mesure où v1 et v2 se disputent une ressource partagée comme un enregistrement http. Mais les développeurs qui participent à cet écosystème de packaging doivent absolument comprendre que les v1 et v2 de leurs packages devront coexister dans de gros programmes. De nombreux packages n'auront pas besoin de travail - yaml et blackfriday, par exemple, sont tous deux sur la v2 qui sont complètement différents de la v1 mais il n'y a pas d'état partagé pour se battre, donc il n'y a pas besoin de coordination explicite - mais d'autres le feront.

@powerman @rsc
Je développe un package d'interface graphique, ce qui signifie que je ne peux même pas avoir plus de 2 instances en raison de l'utilisation du thread "principal". Donc, venant du pire scénario singleton, c'est ce que j'ai décidé de faire.

  • Avoir seulement une version v0/v1 donc il est impossible d'importer 2+ versions

  • Avoir du code public dans son propre dossier de version api, par exemple v1/v2 en supposant que vgo le permet ou peut-être api1/api2.

  • Ces packages d'API publics dépendront alors d'un package interne, donc au lieu d'avoir à réécrire sur une v2, il s'agit d'une réécriture progressive à mesure que le package grandit et est beaucoup plus facile à gérer.

Dans https://github.com/golang/go/issues/24301#issuecomment -377529520, la modification proposée définit le "nouveau" code comme du code avec un fichier go.mod dans le même répertoire ou un répertoire parent. Cela inclut-il les fichiers go.mod "synthétisés" créés à partir de la lecture des dépendances d'un Gopkg.toml par exemple ?

@zeebo , oui. Si vous avez un fichier go.mod dans votre arborescence, l'hypothèse est que votre code se construit réellement avec vgo. Si ce n'est pas le cas, alors rm go.mod (ou du moins ne l'enregistrez pas dans votre référentiel où d'autres pourraient le trouver).

@AlexRouSg , votre plan pour votre package GUI me semble logique.

@rsc hmm .. Je ne suis pas sûr de comprendre et désolé si je n'ai pas été clair. Un paquet avec seulement un Gopkg.toml dans l'arborescence de fichiers compte-t-il comme "nouveau" pour la définition ?

@rsc

En ce qui concerne le code généré plus généralement, un véritable système de construction inter-langage est la réponse, en particulier parce que nous ne voulons pas que chaque utilisateur ait besoin d'avoir les bons générateurs installés. Mieux vaut que l'auteur lance les générateurs et vérifie le résultat.

Nous avons réussi à résoudre ce problème en mappant protobuf dans le GOPATH. Oui, nous l'avons fait pour que les utilisateurs occasionnels n'aient pas besoin des outils pour mettre à jour, mais pour ceux qui modifient et régénèrent les protobufs, la solution dans protobuild fonctionne extrêmement bien.

La réponse ici est assez décevante. Trouver un nouveau système de construction qui n'existe pas n'est qu'une non-réponse. La réalité ici est que nous ne reconstruirons pas ces systèmes de construction et nous continuerons à utiliser ce qui fonctionne, en évitant l'adoption du nouveau système vgo.

vgo ne fait-il que déclarer faillite pour ceux qui ont aimé et adopté GOPATH et ont contourné ses problèmes ?

@zeebo , non, avoir un Gopkg.toml ne compte pas comme nouveau ; ici "nouveau" signifie qu'il est prévu d'utiliser des importations de style vgo (versions d'importation sémantique).

@stevvooe :

Nous avons réussi à résoudre ce problème en mappant protobuf dans le GOPATH. ...
Vgo déclare-t-il simplement faillite pour ceux qui ont aimé et adopté GOPATH et ont contourné ses problèmes ?

Je n'ai pas regardé votre protobuild, mais en général, oui, nous passons à un modèle non-GOPATH, et certaines des astuces que GOPATH aurait pu activer seront laissées de côté. Par exemple, GOPATH a permis au godep d'origine de simuler la vente sans avoir de support de vente. Ce ne sera plus possible. En un coup d'œil rapide, il semble que protobuild soit basé sur l'hypothèse qu'il peut déposer des fichiers (pb.go) dans d'autres packages que vous ne possédez pas. Ce genre d'opération globale ne sera plus pris en charge, non. Je suis tout à fait sérieux et sincère de vouloir m'assurer que les protobufs sont bien pris en charge, distincts de vgo. @neild serait probablement intéressé d'entendre des suggestions, mais peut-être pas sur cette question.

@stevvooe compte tenu des commentaires de @rsc dans https://github.com/golang/go/issues/24301#issuecomment -377602765 J'ai renvoyé https://github.com/golang/protobuf/issues/526 au cas où ce problème finit par couvrir l'angle vgo . Si les choses finissent par être traitées ailleurs, je suis sûr que @dsnet et al nous indiqueront.

Remarque : je n'ai pas vu de près les commentaires précédents, il semble que le problème soit résolu avec une approche différente. Ci-dessous était mon idée.

Juste une idée.

Que diriez-vous de rendre vgo get une balise spécifique consciente comme vgo-v1-lock ?
Lorsqu'un référentiel a la balise, il peut ignorer d'autres balises de version et être épinglé à la balise.

Ainsi, lorsqu'un référentiel a marqué v2.1.3 comme dernière version,
mais aussi le propriétaire pousse la balise vgo-v1-lock vers le même commit qui est étiqueté v2.1.3
il pourrait écrire go.mod

require (
    "github.com/owner/repo" vgo-v1-lock
)

Il ne devrait pas être mis à jour même si vgo get -u , tant que le propriétaire du référentiel n'a pas modifié ou supprimé la balise.
Cela pourrait faciliter la préparation des grands dépôts pour leur déménagement.

Lorsqu'un auteur de bibliothèque est prêt, l'auteur peut annoncer à l'utilisateur
qu'ils pourraient mettre à jour manuellement en mettant "/v2" dans son chemin d'importation.

Comment gérons-nous le cas où il est nécessaire de corriger une dépendance profonde (par exemple pour appliquer un correctif CVE que l'auteur d'origine n'a pas encore publié dans une balise). Il semble que la stratégie du fournisseur puisse gérer cela puisque vous pouvez appliquer un correctif à la version originale des auteurs. Je ne vois pas comment vgo peut gérer cela.

@chirino , vous pouvez utiliser la directive replace dans le fichier go.mod pour pointer vers le package corrigé.

@rsc

En un coup d'œil rapide, il semble que protobuild soit basé sur l'hypothèse qu'il peut déposer des fichiers (pb.go) dans d'autres packages que vous ne possédez pas.

Ce n'est pas du tout ce que fait le projet. Il crée un chemin d'importation à partir de GOPATH et du répertoire du fournisseur. Tous les fichiers protobuf de votre projet seront ensuite générés avec ce chemin d'importation. Il fait également des choses comme les importations de cartes vers des packages Go spécifiques.

L'avantage de ceci est que cela permet de générer des protobufs dans un projet feuille qui dépendent d'autres protobufs définis dans des dépendances sans tout régénérer. Le GOPATH devient effectivement les chemins d'importation pour les fichiers protobuf.

Le gros problème avec cette proposition est que nous perdons complètement la capacité de résoudre les fichiers dans les projets relatifs aux packages Go sur le système de fichiers. La plupart des systèmes d'emballage ont la capacité de le faire, même s'ils le rendent difficile. GOPATH est unique en ce sens qu'il est très facile de le faire.

@stevvooe Je suis désolé mais je suppose que je suis toujours confus quant à ce que fait le protobuild. Pouvez-vous déposer un nouveau problème "x/vgo : non compatible avec protobuild" et donner un exemple simple et fonctionnel d'une arborescence de fichiers qui existe aujourd'hui, ce que protobuild ajoute à l'arborescence et pourquoi cela ne fonctionne pas avec vgo ? Merci.

Que faire si le nom du module doit changer (domaine perdu, changement de propriétaire, litige de marque, etc.) ?

@jimmyfrasche

En tant qu'utilisateur :
Ensuite, en tant que correctif temporaire, vous pouvez modifier le fichier go.mod pour remplacer l'ancien module par un nouveau tout en conservant les mêmes chemins d'importation. https://research.swtch.com/vgo-tour

Mais à long terme, vous souhaiterez modifier tous les chemins d'importation et modifier le fichier go.mod pour utiliser le nouveau module. Fondamentalement, la même chose que vous auriez à faire avec ou sans vgo.

En tant que mainteneur du paquet :
Mettez simplement à jour le fichier go.mod pour modifier le chemin d'importation du module et informez vos utilisateurs du changement.

@jimmyfrasche ,

Que faire si le nom du module doit changer (domaine perdu, changement de propriétaire, litige de marque, etc.) ?

Ce sont des problèmes réels et préexistants que la proposition vgo ne tente pas de résoudre directement, mais il est clair que nous devrions éventuellement les résoudre. La réponse à la disparition du code est d'avoir des proxys de mise en cache (miroirs) avec une raison de leur faire confiance ; c'est un travail futur. La réponse au déplacement de code est d'ajouter un concept explicite de redirection de module ou de package, un peu comme les alias de type sont des redirections de type ; c'est aussi un travail futur.

La réponse à la disparition du code est d'avoir des proxies de mise en cache (miroirs)

IMO c'est vraiment pour les entreprises. La plupart des petites entreprises et d'autres seraient parfaitement d'accord avec la vente et l'engagement de toutes les dépendances dans le même référentiel

Classé # 24916 pour la compatibilité que j'ai mentionnée dans le commentaire ci-dessus.
Également déposé # 24915 proposant de revenir à l'utilisation directe de git etc au lieu d'insister sur l'accès HTTPS. Il semble clair que les configurations d'hébergement de code ne sont pas encore prêtes pour l'API uniquement.

proposition mineure pour créer une cohérence dans les fichiers mod avec la commande vgo get prévue

Dans le document "vgo-tour", la commande vgo get s'affiche comme :

vgo get rsc.io/[email protected]

Que diriez-vous de refléter ce format dans le fichier mod ? Par example:

module "github.com/you/hello"
require (
    "golang.org/x/text" v0.0.0-20180208041248-4e4a3210bb54
    "rsc.io/quote" v1.5.2
)

pourrait être simplement :

module "github.com/you/hello"
require (
    "golang.org/x/[email protected]"
    "rsc.io/[email protected]"
)
  • améliore la cohérence avec la ligne de commande
  • l'identifiant unique définit complètement l'élément
  • meilleure structure pour prendre en charge les opérations définies dans le fichier mod qui nécessitent plusieurs identifiants de package versionnés

Chercher plus de clarté sur la façon dont cette proposition traite de la distribution de paquets "binaire uniquement".

la gestion des versions / distribution de la bibliothèque binaire ne semble apparaître dans aucun des documents de description autour de vgo. est-il nécessaire de regarder cela plus attentivement?

De la façon dont cela fonctionne aujourd'hui, si je peux utiliser l'outil simple git , go get fonctionnera très bien. Peu importe qu'il s'agisse d'un référentiel Github privé ou de mon propre serveur Git. Je l'aime vraiment.

D'après ce que je comprends, il va être impossible de continuer à travailler de cette façon. Est-ce vrai? Si oui, est-il possible de conserver l'option d'utiliser un binaire git installé localement afin de vérifier le code ? (événement où il utilise un indicateur CLI explicite)

@korya Veuillez consulter le problème récemment déposé https://github.com/golang/go/issues/24915

@sdwarwick , concernant https://github.com/golang/go/issues/24301#issuecomment -382791513 (syntaxe go.mod), voir #24119.

re https://github.com/golang/go/issues/24301#issuecomment -382793364, il est possible que je ne comprenne pas ce que vous voulez dire, mais go get n'a jamais pris en charge les packages binaires uniquement, et nous ne prévoyons pas pour ajouter du soutien. Il est trop difficile d'énumérer tous les différents binaires possibles dont on pourrait avoir besoin. Mieux vaut exiger la source et pouvoir recompiler lorsque les dépendances ou le compilateur changent.

@rsc Je crois que https://github.com/golang/go/issues/24301#issuecomment -382793364 fait référence à
https://golang.org/pkg/go/build/#hdr -Binary_Only_Packages

@AlexRouSg Oui. Ceux-ci ne sont pas pris en charge par "go get" (mais "go build" les prend en charge en tant que type de construction), ce à quoi @rsc fait référence. La distribution de ces types de packages doit être effectuée en externe à l'outil "go get", et donc probablement la même chose pour cette nouvelle proposition.

Je m'attends à ce que la prise en charge actuelle des packages binaires uniquement continue de fonctionner aussi mal qu'elle l'a jamais fait. Je ne ferai aucun effort pour l'enlever.

J'ai à nouveau mis à jour le résumé de la discussion. J'ai également déposé # 25069 pour ma suggestion plus tôt sur la sensibilisation minimale aux modules dans l'ancien cmd/go.

@kybin , concernant https://github.com/golang/go/issues/24301#issuecomment -377662150 et la balise vgo-v1-lock , je vois l'attrait mais ajouter un cas spécial pour cela signifie ajouter plus de cas spéciaux tout au long le reste du support du module. Je ne pense pas que le bénéfice soit proportionnel au coût dans ce cas. Les gens peuvent déjà utiliser des pseudo-versions pour obtenir un effet similaire. Je crains également que la balise se déplace et/ou que les gens ne respectent pas correctement la rétrocompatibilité (par exemple, déplacer vgo1-v1-lock de la v2.3.4 à la v3.0.0 juste pour éviter la gestion des versions d'importation sémantique). Donc, dans l'ensemble, je pense que nous ne devrions probablement pas faire cela.

Je pense qu'il est temps de marquer cette proposition comme acceptée.

Il n'y a jamais eu de suspens quant à savoir si cela serait accepté sous une forme ou une autre. Au lieu de cela, le but de la discussion ici était de déterminer la forme exacte, d'identifier ce que nous devrions ajuster. Comme je l'ai écrit dans le billet de blog :

Je sais qu'il y a des problèmes avec cela que l'équipe Go et moi ne pouvons pas voir, car les développeurs Go utilisent Go de nombreuses façons intelligentes que nous ne connaissons pas. L'objectif du processus de retour d'information sur la proposition est que nous travaillions tous ensemble pour identifier et résoudre les problèmes de la proposition actuelle, afin de nous assurer que l'implémentation finale qui sera livrée dans une future version de Go fonctionne bien pour autant de développeurs que possible. Veuillez signaler les problèmes liés à la question de la discussion de la proposition. Je garderai le résumé de la discussion et la FAQ mis à jour au fur et à mesure que les commentaires arriveront.

Le résumé de la discussion et la FAQ sont à jour en ce moment. La discussion ici et hors numéro a entraîné les changements importants suivants :

  • sensibilisation minimale au module dans l'ancien cmd/go, #25069.
  • restauration du support fournisseur minimal, #25073.
  • restauration de la prise en charge de l'accès direct à Git, #24915.
  • supprimez les guillemets dans go.mod, #24641.
  • meilleur support pour gopkg.in, #24099, autres.
  • prise en charge de la dénomination des commits par identifiants de branche, #24045.

Cela a également suscité des discussions sur la possibilité de modifier le nom et la syntaxe du fichier go.mod, mais le seul changement qui en a résulté a été de supprimer les guillemets.

La discussion s'est tue, et aussi elle est devenue assez longue pour être assez pénible à charger sur GitHub (apparemment 100 commentaires c'est trop !). En marquant la proposition comme acceptée, nous pouvons nous concentrer sur l'utilisation de vgo et la préparer pour l'inclusion dans Go 1.11 en tant qu'"aperçu", et nous pouvons passer aux problèmes que GitHub peut charger plus rapidement.

Il y a, bien sûr, encore plus de bogues à trouver et à corriger, et plus d'ajustements de conception à faire. Des discussions sur ces détails peuvent être faites sur de nouvelles questions spécifiques à ces détails. Veuillez utiliser un préfixe "x/vgo:" et le jalon vgo .

Merci tout le monde.

@rsc Quelle est la façon d'essayer vgo maintenant ? Devrions-nous récupérer et construire github.com/golang/vgo ou github.com/golang/go ?

@ngrilly continue d'utiliser go get -u golang.org/x/vgo .

@rsc merci pour le travail acharné et le temps que vous avez consacré à cette proposition. J'espère vraiment que nous finirons par arriver à un point où il y aura une bonne histoire autour de la gestion des dépendances Go.

Je pense qu'il est temps de marquer cette proposition comme acceptée.

Je ne pense pas qu'il soit approprié pour une personne qui soumet une proposition de déclarer quand elle est prête à être acceptée. Je pense que ceux qui soumettent une proposition, en particulier une aussi grande et opiniâtre, ne devraient pas avoir leur mot à dire sur son acceptation. Leur soumission de la proposition communique leurs préjugés. D'un autre côté, je pense que les auteurs devraient certainement avoir leur mot à dire sur le rejet de la proposition s'ils changent d'avis après l'avoir soulevée.

À l'heure actuelle, j'ai l'impression qu'il existe des désaccords profonds autour des décisions techniques au sein vgo , celles qui, je le crains, fragmenteront l'écosystème _et_ la communauté. Dans cet esprit, je pense que nous devrions accorder un peu plus de temps pour que les propositions concurrentes soient terminées et mises en lumière. Une fois que cela se produit, nous devons avoir une partie _neutre_ composée de représentants de plusieurs entreprises et de la communauté, pour faciliter la discussion et la décision finale.

Je crains de plus en plus qu'une bonne partie de la direction de Go soit devenue trop isolée de la communauté derrière Go (y compris d'autres entreprises qui l'utilisent), et que le langage et l'écosystème commencent à en souffrir. C'est pourquoi je pense que nous devons avoir un groupe neutre, avec une représentation qui reflète les utilisateurs du langage de programmation Go, pour aider à ratifier des propositions comme celle-ci.

En fin de compte, travailler en tant qu'ingénieur logiciel au sein de Google entraîne une perspective différente par rapport à une grande partie de l'industrie. Avoir la masse critique de développeurs principaux au sein de Google ne contribue pas à la diversité dont nous avons besoin pour aller de l'avant.

@theckman Votre ligne de pensée semble être :

  1. Les décisions concernant Go sont prises par une petite équipe composée principalement d'ingénieurs Google.
  2. Les ingénieurs de Google sont isolés du reste de la communauté, car les besoins de Google sont très spécifiques.
  3. Cela conduit à des décisions qui favorisent la perspective de Google et ne sont pas adaptées aux autres utilisateurs de Go.
  4. Cela pourrait blesser et fragmenter la communauté Go.
  5. Pour résoudre ce problème, Go devrait adopter un processus de décision formel où les décisions sont prises collégialement par un groupe reflétant la diversité de la communauté Go (quelque chose de "démocratique").

En théorie, je serais enclin à aimer tout ce qui est "démocratique", mais en pratique :

  • Je ne pense pas que les décisions prises par l'équipe Go soient biaisées en faveur des besoins de Google, au détriment des "petits" utilisateurs de Go. En tant que développeur dans une toute petite boutique (tout le contraire de Google), j'ai l'impression que Go est très bien adapté à nos besoins, et je connais d'autres petites équipes autour de moi qui utilisent Go avec bonheur. Personnellement, les seuls reproches que j'ai avec le langage Go ont été reconnus par l'équipe Go (gestion des dépendances, manque de génériques, gestion des erreurs verbeuses) et je suis convaincu qu'ils y travaillent. Pourriez-vous donner des exemples de décisions prises par l'équipe Go qui auraient été différentes et auraient mieux servi "le reste de la communauté" si nous avions eu un processus "démocratique" ?

  • Je ne suis pas convaincu que l'adoption d'un processus de décision "démocratique" résoudrait automatiquement les problèmes que vous avez mentionnés et éliminerait le risque de "fragmentation" de la communauté. Cela peut être une amélioration par rapport au modèle BDFL , mais ce n'est pas une garantie de stabilité en soi. L'histoire open source, et l'histoire humaine en général, fournit de nombreux exemples de sociétés démocratiques qui ont été ruinées par des désaccords et des conflits.

@theckman , alors que @ngrilly essayait d'être poli, je serai concret : si vous voyez des problèmes techniques pour lesquels la proposition de vgo n'est pas prête à être acceptée, dites-le nous dès que possible et ici ! Si vous pensez que certains problèmes connus n'ont pas été correctement traités, dites-le nous. S'il n'y a pas de tels cas - quelle est la différence qui dira "il est temps d'accepter la proposition" ? Nous avons eu deux mois pour en discuter, si vous pensez qu'il y a une raison technique pour laquelle ce n'est pas suffisant, dites-le nous.

On dirait que vous voulez ajouter plus de politique ici sans raison, ce qui ne fera que tout ralentir, et c'est si nous avons la chance et que cela ne fait aucun autre mal. Et même si vous pensez qu'il y a une raison à cela - ce n'est pas le bon endroit pour en discuter - veuillez commencer cette discussion dans la liste de diffusion à la place.

Désolé pour un autre commentaire hors sujet, tout le monde !

@powerman Désolé d'être nul et de citer mon commentaire précédent :

À l'heure actuelle, il semble qu'il existe des désaccords profonds autour des décisions techniques au sein de vgo, celles qui, je le crains, fragmenteront l'écosystème et la communauté. Dans cet esprit, je pense que nous devrions accorder un peu plus de temps pour que les propositions concurrentes soient terminées et mises en lumière.

Je sais qu'il y a des propositions alternatives qui arrivent, et ma demande était de mettre le holà à accepter cela jusqu'à ce que ceux-ci aient l'heure de la journée. Nous n'avons pas eu de gestion des dépendances depuis un certain temps maintenant, donc je pense qu'il n'est pas déraisonnable de demander un court séjour tout en permettant de peaufiner d'autres propositions.

Je ne suis pas sûr qu'il soit facile de bien l'articuler dans ce numéro, simplement parce que le format est un peu contraint. Même dans ce cas, j'hésiterais, car je dupliquerais essentiellement des parties des propositions WIP. Je ne voudrais pas fragmenter les idées ou voler la vedette aux auteurs.

Cependant, sachant que ces propositions sont en cours et qui y travaille, il a semblé que la déclaration selon laquelle cela était prêt était une tentative active d'étouffer ces opinions concurrentes. Je me suis senti obligé de soulever ces préoccupations en raison des tendances que j'ai observées au cours de mes années en tant que Gopher. Je veux sincèrement que la langue, l'écosystème et la communauté réussissent, et ceux-ci sont élevés uniquement dans cet objectif.

Edit : Pour clarifier, par court séjour je ne veux pas dire deux mois ou quelque chose comme ça. Je veux dire quelques semaines.

@ngrilly Désolé, je ne voulais pas ignorer votre commentaire. J'avais prévu de l'adresser au précédent, mais j'ai fini par être plus verbeux que je ne le voulais.

Je pense qu'il y a deux problèmes. Bien que j'estime qu'il y a quelque chose à discuter dans un forum différent sur la façon dont ces décisions sont prises, c'est pourquoi j'ai ajouté un peu de contexte autour de cela, je veux vraiment me concentrer sur la mise en pause temporaire de l'acceptation de cette proposition jusqu'à ce que ces autres propositions aient avait la chance de devenir public.

Je sais qu'il y a des propositions alternatives qui arrivent, et ma demande était de mettre le holà à accepter cela jusqu'à ce que ceux-ci aient l'heure de la journée. ... [S]achant que ces propositions sont en cours et qui y travaille, il a semblé que la déclaration selon laquelle cela était prêt était une tentative active d'étouffer ces opinions concurrentes.

Je vous assure que non. J'ai été assez clair sur la chronologie ici. Mon premier message de la mi-février indique que l'objectif est d'intégrer la proposition vgo dans Go 1.11 ; le gel du développement approche. Je ne sais rien des autres propositions en cours ou de qui y travaille. C'est nouveau pour moi. Si les gens veulent s'engager avec cette proposition ou faire des contre-propositions, cette proposition est ouverte depuis un mois et demi, donc il se fait un peu tard.

Pour être clair, je n'ai pas marqué la proposition comme acceptée, malgré ce que Golang Weekly et peut-être d'autres ont rapporté. J'ai seulement dit que je pense qu'il est temps de le faire. C'est-à-dire que je n'ai pas appliqué l'étiquette Proposition-Acceptée, exactement parce que je voulais d'abord vérifier qu'il y avait un consensus général pour le faire. Et le consensus général semble être en faveur de l'acceptation, du moins à en juger par la discussion globale ici ainsi que par les compteurs emoji sur https://github.com/golang/go/issues/24301#issuecomment -384349642.

Je sais qu'il y a des propositions alternatives qui arrivent

@theckman , si vous savez quelque chose comme ça, vous êtes probablement le seul à le savoir. À ce jour, je n'ai vu personne soulever ce problème jusqu'à présent. Je pense que les déclarations de Russ sur le fait de vouloir essayer cela pour Go 1.11 étaient très claires dès le début, donc si quelqu'un travaille sur des propositions alternatives, il avait environ 2 mois pour les proposer, même en guise d'avertissement.

Je pense aussi que nous pouvons accepter le fait que l'équipe Go a une bonne réputation de ne pas prendre de décisions sur un coup de tête, et si nous regardons juste comment ils ont retiré l'Alias ​​au dernier moment de Go 1.8 car ce n'était pas le bon chose à faire à ce moment-là, alors nous devrions probablement leur donner la courtoisie de leur permettre au moins de construire leur propre expérience/solution.

En fin de compte, la proposition apporte bien plus qu'un simple algorithme sur la façon de sélectionner la version de la dépendance à utiliser. Si quelqu'un trouve un moyen de l'améliorer, il y a deux options : le soumettre via le processus CL normal OU créer son propre outil et laisser la communauté l'utiliser, s'il le souhaite. L'équipe Go peut toujours fournir sa propre version de l'outil à mon humble avis, donc je ne vois pas que cela a un problème fermé.

Cependant, gardez à l'esprit que la plupart des actions de division ont été prises jusqu'à présent par la communauté, et non par l'équipe Go. Donnons à l'équipe Go leur chance de construire un outil, puis évaluons-le, lorsqu'il est viable de le faire, puis apportons des arguments sur la façon de l'améliorer et d'aller de l'avant plutôt que d'écrire à quel point il est mauvais.

Veuillez considérer cela comme faisant partie d'un autre type de rapport d'expérience : celui où j'étais un adversaire _très_ vocal de la proposition d'Alias ​​pour ensuite comprendre et maintenant voir la proposition en action.

Edit : le message d'origine avait une omission très malheureuse record of *not* making decisions on a whim aurait dû être le texte, malheureusement la partie "not" manquait. Mes excuses pour cela.

J'ai une description détaillée des préoccupations fondamentales concernant la proposition. J'ai essayé de terminer cet article afin de pouvoir les présenter tous en même temps - c'est un domaine complexe et subtil et en tant que tel, ces problèmes doivent être traités dans leur intégralité - mais la vie et le travail ont rendu cela difficile.

Bien que j'aie fait allusion à cet article dans Slack, et que j'en ai discuté directement avec @rsc , j'ai choisi de ne pas en faire mention ici jusqu'à présent. Il m'a semblé que publier cet article avant que je sois prêt à le publier complètement ne serait pas très constructif. Mais, comme cela a été noté, cela fait deux mois, donc je vais faire un gros effort pour lancer la série la semaine prochaine.

(edit : ce sont les "alternatives" auxquelles @theckman faisait référence)

@sdboyer Vous avez mentionné que vous aviez plusieurs préoccupations. Pourriez-vous s'il vous plaît au moins publier leur liste maintenant?
Je travaille avec plusieurs systèmes qui amènent l'enfer des dépendances à un autre niveau (chef, go, npm, compositeur) et par expérience, cette proposition est une solution à tous en ce qui concerne le go.

@theckman , pouvez-vous confirmer que vous ne faisiez référence qu'aux commentaires de @sdboyer ? Ce n'est pas un secret. Sam l'a mentionné littéralement le premier jour de la sortie de vgo ("j'écris des documents plus détaillés sur mes préoccupations" - https://sdboyer.io/blog/vgo-and-dep/). Mais c'est un retour d'expérience, pas une proposition, et vous avez fait référence à plusieurs reprises à "autres propositions", au pluriel. En savez-vous plus ?

Quelles sont les implications de vgo pour les utilisateurs de l'API go/types ? Quel est l'état actuel de la prise en charge de go/types ?

J'ai reçu un PR mdempsky/gocode#26 pour ajouter une implémentation vgo-aware go/types.Importer, mais je ne sais pas si/pourquoi cela est nécessaire.

En supposant que cela soit nécessaire, pouvons-nous ajouter un importateur go/types. ?

Je n'ai pas vraiment suivi les détails de vgo, alors c'est peut-être simplement "sans impact", mais je ne vois aucune mention de go/types ci-dessus. Les recherches Google pour "vgo go/types golang" sont également non informatives.

Merci.

@mdempsky , le plan est d'avoir un chargeur de packages compatible avec vgo (et d'ailleurs, compatible avec le cache), probablement golang.org/x/tools/go/packages, mais il n'existe pas encore. Les gens devraient attendre ce paquet au lieu d'écrire du code qui devra être jeté. Ne fusionnez pas le PR. Je l'ai commenté.

@mdempsky allait répondre sur https://github.com/mdempsky/gocode/pull/26 mais je répondrai ici pour l'instant.

https://github.com/mdempsky/gocode/pull/26 est entièrement jetable ; juste une preuve de concept qui utilise un CL maintenant abandonné contre vgo .

Je viens de voir la réponse de @rsc , je signale donc simplement qu'il y a aussi une discussion en cours sur https://github.com/golang/go/issues/14120#issuecomment -383994980.

Résumé : après quelques années d'expérience avec les versions, la dernière meilleure tentative était un algorithme très complexe, un solveur sat. Mais si vous apportez quelques modifications simples aux données d'entrée, le problème de décision NP-complet devient non seulement gérable, mais très rapide.

En tant qu'utilisateur de Go en petite équipe avec beaucoup d'expérience dans l'utilisation de NPM, j'aime beaucoup la proposition de vgo. FWIW, j'ai hâte que vgo soit implémenté dans go proprement dit et le plus tôt sera le mieux pour mon équipe et moi.

Non pas que je sois quelqu'un de spécial, juste que depuis que j'ai vu des discussions sur les problèmes des petites équipes, j'ai pensé que j'interviendrais.

Voici mon avis.

En surface, la section _Proposition_ de la dernière révision du document de proposition semble correcte, sinon très spécifique (par exemple, il n'est pas clair dans quelle mesure Subversion peut être pris en charge). Une exception est que "Interdire l'utilisation des répertoires de fournisseurs, sauf dans une utilisation limitée" semble indiquer que les répertoires de fournisseurs ne seront pas du tout pris en charge dans les packages non-modules ; est-ce vrai?

D'autre part, la proposition implique certaines décisions de conception et de mise en œuvre qui compromettent divers avantages du go get actuel. Les pertes peuvent être acceptables, certaines peuvent être évitées, mais si vgo get doit remplacer go get , elles doivent être traitées comme des considérations de conception et discutées, car sinon nous pourrions nous retrouver avec un outil qui est pas un remplacement adéquat, et soit vgo ne sera pas fusionné en go ou go get devra être ressuscité en tant qu'outil tiers.

La section _Implementation_ indique : "Dans une version ultérieure (par exemple, Go 1.13), nous mettrons fin à la prise en charge de Go Get des non-modules. Le soutien au travail dans GOPATH se poursuivra indéfiniment. C'est gênant. Premièrement, il y a beaucoup de bons projets qui n'ont pas été mis à jour depuis des années. Ils fonctionnent toujours grâce à la promesse de compatibilité Go 1, mais beaucoup n'ajouteront pas de fichiers go.mod . Deuxièmement, cela oblige les développeurs de projets sans dépendances ou ceux qui ne se soucient pas des versions à ajouter des fichiers de module ou à s'abstenir du nouvel écosystème go get . Vous pouvez être justifié de vouloir cela, mais veuillez expliquer pourquoi. (Pour moi, cela semble inutilement lourd ; je préfère utiliser le fork de l'ancien go get . Je reconnais que les gestionnaires de paquets pour d'autres langages sont encore plus lourds, et je suis sûr que vgo est meilleur qu'eux, mais il ne gère pas mieux mes cas d'utilisation que l'actuel go get , avec l'aide occasionnelle du gouverneur ).

Ma principale préoccupation concernant vgo vs go concerne le flux de travail qu'ils prennent en charge. Je l'avais exprimé au post vgo-intro. Cela pourrait largement appartenir à la section _Compatibilité_ de la proposition, ou cela pourrait être hors de son champ d'application, mais cela correspond à d'autres questions et problèmes soulevés ici.

Pour référence, voici une copie de mon commentaire vgo-intro.

Dans certaines versions ultérieures, nous supprimerons la prise en charge de l'ancien go get sans version.

Alors que d'autres aspects de la proposition sonnent bien, celui-ci est malheureux. (À tel point que si je devais choisir entre incorporer le versioning dans la chaîne d'outils go et continuer à travailler avec des outils de contrôle de version, je choisirais ce dernier.) L'avantage de vgo est qu'il facilite les builds reproductibles et retarde la rupture de votre projet en raison de mises à jour incompatibles jusqu'à ce que vous, en tant qu'auteur du projet (avec le fichier go.mod), vouliez y faire face ; mais l'avantage de go get est qu'il apporte les avantages d'un monorepo au monde multi-dépôt : grâce aux clones complets des dépendances, vous pouvez travailler avec eux aussi facilement qu'avec votre propre projet (inspecter l'historique, modifier, différencier les changements ; allez à la définition de n'importe quoi et blâmez-le), cela facilite la collaboration (vous poussez simplement et proposez vos changements) et impose généralement la vision qu'à tout moment il n'y a qu'un seul état actuel du monde - la pointe de chaque projet - et tout le reste c'est l'histoire. Je pense que cette approche unique (en dehors des monorepos réels) est une aubaine distinctive de l'écosystème Go qui a fait plus de bien que de mal, et elle ne devrait pas être abandonnée.

Une conséquence négative plus subtile de la proposition est qu'elle rend la gestion des versions incurable et héréditaire : une fois qu'un projet marque une version, il ne peut pas s'attendre à ce que les modifications futures atteignent les utilisateurs sans marquer les nouvelles versions. Même si l'auteur d'origine reste déterminé à continuer à taguer, les auteurs des forks sont désormais obligés soit de les taguer eux aussi (ce qui est particulièrement gênant si le projet source est toujours actif), soit de supprimer les anciennes balises.

Dans l'ensemble, je tiens à souligner que l'approche Go actuelle de la gestion des dépendances est globalement supérieure à la gestion des versions. Il s'aligne mieux avec l'open source moderne, dynamique et collaborative qui s'attend à ce que tous les commits soient visibles, et publier uniquement les sources des versions (ou "intégrer les changements internes" dans d'énormes commits non descriptifs) ne suffit pas (car cela réduit considérablement la visibilité, la collaboration et dynamisme). On peut voir à la fois dans les monorepos et dans l'écosystème Go actuel que la plupart des projets n'ont pas besoin de versions. Bien sûr, cette approche n'est pas ultime, elle a des inconvénients et il est important de prendre en charge les projets versionnés également, mais cela ne doit pas se faire au détriment des versions sans version.

Pour résumer, le go get actuel (avec des outils auxiliaires, par exemple godef ) prend en charge le flux de travail qui comprend :

  • code source modifiable des dépendances
  • code source des dépendances sous leur VCS
  • dernières révisions des dépendances

Je suppose que je peux supposer que le code source des dépendances restera modifiable, c'est-à-dire godef sera lié à des _fichiers_ qui ne sont _pas protégés en écriture_ et _utilisés pendant la construction_. Cependant, vgo va revenir sur les deux autres points. En ce qui concerne le deuxième point, #24915 a prolongé la prise en charge des outils VCS, mais il déclare toujours l'objectif de l'abandonner ; et le flux de travail nécessite non seulement que les dépendances soient extraites de VCS, mais aussi que l'extraction soit utile pour les développeurs (par exemple, pas une extraction git peu profonde, pas une extraction git avec .git supprimé) et soit utilisée pendant la construction , mais vgo peut ne pas répondre à cette exigence. En ce qui concerne le troisième point, j'ai justifié sa valeur dans le commentaire vgo-intro, mais vgo semble l'abandonner complètement.

Un outil de gestion des versions Go n'a pas besoin d'abandonner la prise en charge du flux de travail actuel, et il ne doit pas l'abandonner pour conserver les avantages uniques de travailler dans l'écosystème Go et remplacer adéquatement go get . La conception de vgo rend cela difficile, mais pas évidemment infaisable. La section _Proposition_ de la proposition, en revanche, semble presque compatible avec le flux de travail actuel. Le seul défi qu'il présente pour prendre en charge le troisième point (vérification de la dernière révision) - et c'est un gros problème - est qu'il est difficile de décider pour les modules ≥v2.0.0 s'ils peuvent être extraits à master , ou s'ils doivent être extraits comme spécifié car master se trouve dans une autre version majeure. Ce n'est pas un défi pour le go get actuel avec gopkg.in parce que tout est extrait à master par défaut, et le contenu de gopkg.in est extrait à la balise ou à la branche correspondante ; mais vgo brouille cette distinction et étend le modèle gopkg.in à tous les packages. (De plus, il arrête de faire correspondre les branches.) En effet, il devient impossible de dire avec certitude et nécessaire de deviner comment obtenir la dernière révision de la version majeure spécifiée.

Je l'ai peut-être manqué, mais comment vgo fonctionnerait-il dans ce scénario ?

  • Je travaille sur le service A et le service B en fonction de la lib X (sur laquelle je travaille également)
  • J'ai besoin d'un changement majeur dans lib X

Avec les façons de faire actuelles, je fais juste mes changements, compile le service A et le service B, ils récupèrent tout ce qui est dans mon $GOPATH pour la lib X, je répare des trucs, puis je pousse la lib X avec une bosse de semver majeure, puis pousse les deux services A et B leur disant d'utiliser la nouvelle majeure de lib X dans leur Gopkg.toml .

Maintenant, lorsque vgo prendra le relais, go build sur mes services essaiera de trouver une nouvelle version non existante de lib X à partir de github, et je peux prévoir toutes sortes de problèmes.

Alors, ai-je raté quelque chose d'évident?

Vous pouvez utiliser la directive replace pour ce type de chose.

Le lundi 30 avril 2018, 12 h 15, Antoine [email protected] a écrit :

Je l'ai peut-être manqué, mais comment vgo fonctionnerait-il dans ce scénario ?

  • Je travaille sur le service A et le service B tous les deux en fonction de la lib X (que je
    travaille aussi)
  • J'ai besoin d'un changement majeur dans lib X

Avec les façons de faire actuelles, je fais juste mes modifications, compile le service A et
service B, ils récupèrent tout ce qui est dans mon $GOPATH pour la lib X, je répare des trucs,
puis je pousse lib X avec une bosse de semver majeure, puis pousse les deux services A et B
leur disant d'utiliser la nouvelle majeure de lib X dans leur Gopkg.toml.

Maintenant, quand vgo prendra le relais, allez s'appuyer sur mes services pour essayer de trouver non
nouvelle version existante de lib X de github, et je peux prévoir toutes sortes de
troubles.

Alors, ai-je raté quelque chose d'évident?


Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/golang/go/issues/24301#issuecomment-385499702 , ou muet
le fil
https://github.com/notifications/unsubscribe-auth/AAuFsfnD8_kbUj8fSXvGgeN77ki6KYM6ks5tt2LLgaJpZM4Sg3bp
.

@kardianos oui, mais cela signifie toujours que je dois pousser mes modifications de bibliothèque pour essayer?

EDIT : il semble que vous puissiez utiliser des chemins pour remplacer (https://github.com/golang/go/issues/24110), ce qui est bien. Mais je peux aussi prédire que cela finira par être commis de nombreuses fois.

Avez-vous l'intention de créer un fichier supplémentaire, comme go.mod.replace ou quelque chose comme ça, afin que nous puissions définir les remplacements dans les environnements de développement et les ignorer ?

@primalmotion Pour éviter les mauvais commits, vous devriez probablement utiliser un crochet git.

Mais je suppose que la bonne réponse est simplement de ne pas le faire (remplacer par le chemin local) trop souvent. Si votre bibliothèque est si étroitement couplée, elle ne devrait pas vivre dans un dépôt séparé (et donc prétendre qu'elle est faiblement couplée). En général, vous devriez pouvoir réparer, tester et publier cette bibliothèque sans tenir compte de l'implémentation actuelle de ces services. Surtout avec vgo, qui garantit que les deux services continueront à utiliser l'ancienne version de lib (qu'ils utilisaient auparavant) jusqu'à ce que vous les mettiez à jour manuellement vers une version plus récente de cette lib. Si vous vous engagez occasionnellement à remplacer des chemins locaux une fois par an - ce n'est pas grave, CI vous aidera à le remarquer et à le résoudre en quelques minutes.

@primalmotion avec un go.mod.replace non versionné vous pouvez valider un projet qui ne sera pas reproductible. Au lieu de cela, avec replace in go.mod vous êtes sûr de valider exactement ce que vous utilisez et testez actuellement.
Cela peut être une erreur de commettre un remplacement, mais vous le remarquerez et le corrigerez.
Ou cela peut être volontaire, je le fais avec des sous-modules, c'est bien quand vous travaillez sur un projet et une bibliothèque ensemble et c'est reproductible si vous validez le sous-module. Je l'ai souvent fait en Python et je l'ai raté avec Go. Avec vgo, je suis heureux de pouvoir à nouveau travailler comme ça. _(j'espère être clair avec mon mauvais anglais, désolé)._

Eh bien, le problème est que nous ne nous soucions pas des versions reproductibles jusqu'à ce que nous décidions que nous nous en soucions (c'est-à-dire lorsque nous préparons des versions). Nous avons un environnement de développement très agile où la mise à jour d'une bibliothèque consiste simplement à vérifier, reconstruire, exécuter des tests. Nous ne commettons pas le Gopkg.lock dans les branches master de nos services, juste le toml avec des versions fixes pour les libs externes, et des contraintes majeures sur les nôtres. Une fois que nous avons créé une branche de version, nous validons le Gopkg.lock et seulement alors nous avons des versions reproductibles (ceci est fait par notre ci).

Vgo brise fondamentalement tous les flux de travail que nous avons construits au fil des ans. Maintenant, juste pour essayer quelque chose d'aussi stupide qu'un petit débogage d'impression dans une bibliothèque (parce que nous faisons tous ça, ne mentez pas :)), ou une petite optimisation, nous devrons passer en revue des dizaines de services, ajouter replace directives partout, testez, puis revenez et supprimez-les toutes.

Qu'est-ce qui pourrait faire que vgo fonctionne pour nous :

  • un système de dérogation comme je l'ai mentionné
  • un moyen de ne pas l'utiliser du tout et de se rabattre sur le bon vieux GOPATH pour le développement.

Et nous voulons vraiment que ça marche pour nous, parce que c'est génial.

Pouvons-nous avoir quelque chose à tester en go 1.11 (il est gelé maintenant) ou peut-être en go 1.12 ?
Il est déjà marqué comme expérimental. Et je pense que plus il y aura de gens qui le testeront en développement réel, plus les retours seront précieux.

J'ai lu sur le problème concernant les packages versionnés. Pour un scénario simple, si j'écris une bibliothèque qui dit utiliser un dep pour l'analyse plist appelé foo-plist . Pour la conséquence de l'analyse, cette bibliothèque plist expose certains types qui lui sont propres. Maintenant, cette bibliothèque passe à la v2 et ma bibliothèque est obligée de passer à la v2 s'il m'arrive de renvoyer des objets de ces types de plist.

Cela semble être assez difficile à résoudre, par exemple, si je souhaite que ma bibliothèque prenne en charge à la fois la v1 et la v2 de ladite bibliothèque plist sous l'impression de cette proposition.

Sous npm, par exemple, ma bibliothèque peut simplement spécifier une dépendance de pair pour dire >=1.0.0|>=2.0.0 et c'est à l'utilisateur de ma bibliothèque de décider quelle version de plist utiliser. Donc, si l'utilisateur de ma bibliothèque foo-plist utilise également une autre bibliothèque qui dépend de plist , alors si les deux bibliothèques sont satisfaites des v1 et v2 de plist, alors l'utilisateur peut choisir lesquelles importer réellement. Plus important encore, si les deux bibliothèques exportent des types plist, ces types sont alors compatibles.

S'ils finissent par être des chemins d'importation différents, je ne pense pas qu'il existe des moyens de prendre en charge cela.

@itsnotvalid foo-plist.2 peut importer foo-plist et réexporter ses types en utilisant des alias de type. Une bonne description de cette technique peut être trouvée ici https://github.com/dtolnay/semver-trick

Aram a souligné ici la difficulté de rétroporter les modifications apportées aux branches (ou répertoires) des versions précédentes. Étant donné que les références "auto" aux sources dans le même module incluent également la version dans le chemin d'importation, soit les correctifs ne seront pas importés proprement, soit on peut introduire par inadvertance des importations entre versions.

Les pensées?

Pour être clair, je suis tout à fait à l'aise avec les importations inter-modules utilisant des versions dans le chemin d'importation ; Je pense que les arguments de Russ ont été très convaincants. Je suis moins clair à leur sujet pour les importations intra-module. Je comprends l'objectif d'avoir un chemin d'importation unique pour un package donné dans une construction (qu'il soit importé entre plusieurs modules ou dans son propre module), mais si je devais choisir, je préférerais avoir une solution pour Le problème d'Aram que de maintenir cette propriété. (De plus, j'imagine que le système de construction pourrait injecter la version à partir du fichier mod lors de la construction d'un module de niveau supérieur, et l'injecter littéralement dans la source après avoir téléchargé une dépendance de module)

@rsc y a-t-il une chance que nous fassions avancer cela ? Je ne vois rien de majeur qui retienne cela.

Je suis désolé si je semble impatient à ce sujet, mais il y a de plus en plus d'outils qui travaillent sur le support de vgo et plus nous retardons cela, plus cela va créer un gâchis pour nous, mainteneurs d'outils, d'aller et venir sur ce .

@sdboyer prévoit de publier ses articles cette semaine. Je dirais qu'il est juste de les attendre.

Je pense que l'algorithme de résolution pour sélectionner les versions de dépendance ne devrait pas être la cause du blocage de l'ensemble de la proposition, qui contient également des éléments tels que les modules, la prise en charge du proxy, la gestion des versions, etc.

Et si, plus tard, nous décidons d'améliorer/changer l'algorithme de téléchargement de ces dépendances, nous pourrons le faire sans affecter quoi que ce soit d'autre.

Je suis d'accord avec @dlsniper - nous sommes déjà bien dans le gel, et cela fait presque trois mois que le design vgo a été introduit. Si son travail sur la 1.11 est encore retardé, je crains qu'il ne soit repoussé à la 1.12.

Le premier article de ce qui sera une série est enfin en ligne . Mes excuses que cela ait pris si longtemps à publier, et qu'il faudra encore plus de temps avant que la série ne soit terminée. Mais, le premier article donne un large aperçu des sujets que j'ai l'intention de couvrir dans toute la série, donc les gens devraient au moins pouvoir avoir une idée de la portée.

En bref : il y a beaucoup de bonnes choses à propos de vgo, dont beaucoup que nous, en tant que communauté, souhaitons depuis longtemps. Cependant, je pense que MVS n'est pas adapté à son objectif et ne devrait pas être mis en production. C'est dommage que tant de ces choses que nous voulons aient été intégrées à MVS, surtout quand si peu d'entre elles lui sont spécifiques. Je travaille sur une approche alternative, qui est référencée à des fins de comparaison tout au long de la série de blogs, et sera articulée dans le post final.

L'algorithme de base alternatif sur lequel je travaille sera probablement assez simple à migrer vers go.mod , donc je ne prévois pas que nous aurions des problèmes, il serait probablement possible de laisser cela aller de l'avant tel quel, si un fichier de verrouillage séparé a été ajouté qui contient la fermeture transitive des dépendances, et a _that_ être ce que le compilateur lit, plutôt que l'algorithme de liste de construction. (Il y a aussi d'autres raisons pour un fichier de verrouillage, bien que ce soit dans le post 5.) À tout le moins, cela nous donne une soupape d'échappement.

Cependant, si nous disons que MVS est OK, même en tant que palliatif, alors il entre et gagne l'avantage de l'inertie. À ce stade, nous devons prouver qu'il est inadéquat pour @rsc (bien qu'en réalité, il l'ait déjà défini comme la norme avant même qu'il ne soit fusionné), et il pense qu'il s'agit d'une affirmation vraie à propos de go get , en ce moment :

Aujourd'hui, de nombreux programmeurs ne font généralement pas attention à la gestion des versions, et tout fonctionne généralement bien.

Compte tenu de tout ce qui précède, je crains que laisser cela aller de l'avant ne crée des "génériques, deuxième tour" - sauf que cette fois, il s'agit de règles qui régissent la façon dont nous interagissons les uns avec les autres, pas avec les machines.

Cependant, si nous disons que MVS est OK, même en tant que palliatif, alors il entre et gagne l'avantage de l'inertie.

Notez qu'à l'heure actuelle , dep a l'avantage de l'inertie (à la fois en étant construit sur les mêmes prémisses que les gestionnaires de versions d'autres langues et en existant depuis plus longtemps avec un large soutien de la communauté). Au moins pour moi, la proposition vgo a tout de même réussi à surmonter cette inertie en étant un bon design, soutenu par de bons arguments.

Personnellement, cela ne me dérange pas si la version de Go est retardée, je suis tout à fait en faveur de faire quelque chose de bien plutôt que de faire vite. Mais au moins pour le moment, vgo me semble toujours être la bonne solution (et AIUI, de nombreuses personnes de la communauté perçoivent cela comme un problème urgent).

@mvdan Ce changement n'est pas sans répercussions. Nous voulons tous cela, mais je pense qu'il est également sage de prendre le temps supplémentaire pour apaiser les doutes, surtout lorsque la personne qui soulève ces doutes a clairement réfléchi au problème.

Je n'arrête pas d'entendre parler du gel et de son impact sur l'obtention d'un aperçu de vgo en 1.11 . Quelle est la ligne officielle à ce stade pour savoir si cela sera intégré pour 1.11 ? Ce problème me semble étonnamment silencieux compte tenu de l'impact potentiel.

@sdboyer , quelle est votre position sur la question de savoir si cela devrait être fusionné en 1.11 étant donné que vous n'avez que _juste_ déclaré officiellement, publiquement, votre position sur MVS ?

Si cela ne se transforme pas en 1.11 , alors nous ne l'aurons pas officiellement disponible en avant-première avant 1.12 en février 2019 et officiellement publié jusqu'au moins 1.13 en août 2019. Cela place la première version potentielle 18 mois après que @rsc a commencé à en discuter. Bien sûr, nous ne devrions pas nous précipiter inutilement, mais comme @Merovius l'a déclaré ci-dessus, de nombreuses personnes, moi y compris, considèrent une réponse officielle à la gestion des dépendances comme une question « urgente ». Attendre 18 mois semble excessif.

Il semblait certainement que dep allait être la réponse officielle et nous y avons converti nos référentiels (et nous avons été satisfaits des résultats). Avec cette proposition dépréciant effectivement dep pour une utilisation à long terme, mais aucun moyen officiel de commencer à intégrer vgo (au moins jusqu'à ce que #25069 soit fusionné), nous nous retrouvons dans la position insatisfaisante d'être obligés de utilisez un outil (avec dep ) dont nous savons qu'il a une durée de vie très limitée.

FWIW, je pense absolument que nous devrions aller de l'avant avec cela en intégrant vgo en tant que proposition dans 1.11 et en incluant #25069 dans 1.11 (et en tant que correctifs pour 1.9 et 1.10 lors de la sortie de 1.11 ).

Honnêtement, je ne comprends pas toutes les implications de MVS et les préoccupations de @ sdboyer à ce sujet. Cependant, compte tenu de son expérience dans ce domaine, je pense que ces préoccupations méritent d'être sérieusement prises en considération. Cela dit, s'il est d'accord pour intégrer vgo avec MVS dans 1.11 (tout en comprenant que sa proposition [toujours en évolution], si elle est acceptée [pour 1.12 ], ne doit pas casser les modules conçu à l'origine pour MVS), alors je ne vois aucune raison de ne pas aller de l'avant.

Je tiens également à remercier @rsc pour cette proposition. J'apprécie que Go ne se soit pas contenté de copier l'approche d'un autre outil et essaie de résoudre ce problème d'une manière qui semble idiomatique. Bien que la gestion des dépendances ne soit jamais amusante, il semble certainement qu'avec cette proposition, Go a le potentiel de faire avancer l'industrie et peut-être même de dépasser les systèmes qui sont actuellement considérés comme les meilleurs.

Juste pour ajouter mon 0,02 $, mon opinion est que MVS est un moment "ah ha" pour la gestion des dépendances. J'apprécie la quantité de réflexion que les gens y ont consacrée, mais je reste convaincu que MVS est là où cela doit aller.

Je suis particulièrement d'accord avec les points que d'autres ont soulevés : les "correctifs de sécurité automatiques" sont au mieux une chimère et au pire une énorme boîte de Pandore.

De plus, je suis avec @joshuarubin : une réponse officielle à la gestion des dépendances est une question urgente. D'autres ont commenté que nous pourrions aller de l'avant avec MVS maintenant et changer plus tard vers d'autres solutions si nécessaire ; si c'est effectivement possible, je pense que c'est la meilleure façon de procéder.

Je propose de découpler les versions majeures des chemins d'importation de la manière suivante. (Je crois que j'ai pris en compte le raisonnement dans vgo-import et que je ne dégrade pas les réalisations de vgo qui y sont énoncées.) Ceci est inspiré par l'idée de # 25069 que go build dans Go 1.9 et 1.10 devrait apprendre à interpréter de manière créative les chemins d'importation (en supprimant la partie version) ; dans ma proposition, l'ancien go build ne change pas, mais vgo apprend une astuce similaire.


Syntaxiquement, les seuls changements sont les suivants :

  1. Dans les fichiers .go , import "repo/v2/pkg" reste import "repo/v2/pkg" si v2 est un répertoire, mais devient import "repo/pkg" sinon. Cela maintient la compatibilité avec le go get actuel.
  2. Dans les fichiers go.mod , module "repo/v2" reste le même s'il se trouve dans le sous-répertoire v2 , mais devient module "repo" s'il se trouve au niveau supérieur. (Il s'agit du préfixe d'importation canonique.)
  3. Dans les fichiers go.mod , vous pouvez également écrire require repo v2.3.4 as repo2 . Ensuite, dans les fichiers .go , vous utiliserez import "repo2/pkg" (ou import "repo2/v2/pkg" si v2 est un répertoire). Cela ne sera pas importable par le go get actuel (sauf si vous utilisez quelque chose comme require github.com/owner/project v2.3.4 as gopkg.in/owner/project.v2 ), mais cela n'est nécessaire que lorsque vous souhaitez utiliser plusieurs versions majeures dans le même module et que la dépendance ne fonctionne pas stocker les versions majeures dans des sous-répertoires, qui ne peuvent de toute façon pas être pris en charge par le go get actuel.

Techniquement, cela vous permet d'écrire go.mod avec :

require repo v1.0.0
require repo v1.1.1 as repo1
require repo v2.2.2 as repo2
require repo v2.3.3 as repo3

mais la sélection de version minimale résoudra ce problème de sorte que repo et repo1 se réfèrent au dépôt à v1.1.1 , et repo2 et repo3 à v2.3.3 . Je ne sais pas si cet aliasing doit être autorisé ou interdit.


Avantages :

  • le code compatible avec le module sera compatible avec le go get actuel, même après la v2.0.0 ; par conséquent:

    • pas besoin de rendre go get minimalement conscient du module (#25069)

    • les projets antérieurs à la v2.0.0 n'auront pas à rompre la compatibilité avec le module-unware go get

  • les projets n'auront pas à attendre que leurs dépendances deviennent des modules avant de devenir eux-mêmes des modules [1]
  • pas besoin de déprécier les projets ignorant les modules ou de décourager les auteurs de démarrer de nouveaux projets ignorant les modules
  • plus facile de garder la prise en charge du flux de travail sans version du go get actuel (expliqué ici et ci- dessus )

Désavantages:

  • peut être gênant de tenir la promesse que les fichiers go.mod déjà écrits continueront de fonctionner (à moins que le nouveau fichier de module ne soit nommé différemment de go.mod )

Ambivalences :

  • le même chemin d'importation dans différents modules peut faire référence à différentes versions majeures

    • bon : plus facile à maintenir après la v2.0.0 et lors d'un changement de version majeur

    • mauvais : vous ne savez pas quelle version majeure vous utilisez sans regarder go.mod

  • les modules peuvent définir des préfixes d'importation arbitraires à utiliser dans leur code

    • certains utilisateurs choisiront de tout importer par un nom court (par exemple import "yaml" avec require gopkg.in/yaml.v2 v2.2.1 as yaml )

[1] Actuellement, vgo peut correctement prendre en charge les dépendances non modulaires uniquement tant qu'aucune dépendance transitive non modulaire d'un module n'est antérieure à la v2.0.0. Sinon, le projet doit attendre que toutes les dépendances qui dépendent indirectement d'un projet antérieur à la v2.0.0 deviennent des modules.

J'ai effectué une analyse des fichiers Gopkg.toml que j'ai pu trouver à partir des packages sur https://github.com/rsc/corpus et j'ai rédigé un résumé sur https://github.com/zeebo/dep-analysis. Sur la base des données disponibles, il semble qu'il n'y ait pas beaucoup de preuves que vgo ne serait pas en mesure de gérer presque tous les cas d'utilisation identifiés.

J'espère sincèrement que cela contribuera à réduire la peur dans la communauté et à parvenir à un accord sur le fait que nous devrions aller de l'avant avec la proposition telle quelle, en nous rappelant qu'il y aura 6 mois supplémentaires pour acquérir une véritable expérience avec l'outil et faire tous les changements nécessaires pour résoudre les problèmes qui pourraient survenir.

Si je te cite :

Près de la moitié de toutes les contraintes ne sont en fait pas du tout des contraintes : elles pointent vers la branche master.

C'est probablement parce qu'il n'existe que master et pas de balises ou "branches nommées comme v2, v3" Si tel est le cas, la comparaison n'est pas juste car vous n'avez pas le choix!

@mvrhov Je ne sais pas ce que vous entendez par "pas juste". Il me semblerait que vgo et dep géreraient très bien ce cas. Ou plutôt, toute alternative réaliste devrait très bien gérer ce cas. En particulier : s'il n'y a pas encore de version publiée, dans un monde vgo, ils pourraient simplement être étiquetés v1.0/v0.x et aucune modification des chemins d'importation (la principale idiosyncrasie de vgo) ne serait nécessaire.

Le but de l'analyse, pour autant que je sache, est d'essayer d'estimer la douleur réelle causée par les différentes approches. Je ne vois pas comment ce cas introduit une douleur réelle pour qui que ce soit.

Cette proposition a fait l'objet de discussions actives pendant plus de deux mois : @rsc et @spf13 ont organisé des séances de rétroaction et recueilli des commentaires précieux de la communauté qui ont abouti à des révisions de la proposition. @rsc a également tenu des réunions hebdomadaires avec @sdboyer afin d'obtenir de plus amples commentaires. Des commentaires précieux ont été fournis sur la proposition, ce qui a donné lieu à des révisions supplémentaires. De plus en plus, ces commentaires portent sur la mise en œuvre qui l'accompagne plutôt que sur la proposition. Après un examen approfondi, nous pensons qu'il est temps d'accepter cette proposition et de laisser le vaste écosystème de développeurs d'outils de Go commencer à effectuer des ajustements critiques afin que notre base d'utilisateurs puisse avoir la meilleure expérience possible.

Il y a eu deux objections à cette proposition dont nous estimons que nous devrions parler :

  1. La proposition obligera les gens à changer certaines de leurs pratiques concernant l'utilisation et la publication de bibliothèques.
  2. La proposition ne fournit pas de solution technique à tous les scénarios possibles impliquant des incompatibilités.

Ceux-ci sont précis dans leur observation mais fonctionnent comme prévu. Les auteurs et les utilisateurs de code _devront_ changer certaines de leurs pratiques concernant l'utilisation et la publication de bibliothèques, tout comme les développeurs se sont adaptés à d'autres détails de Go, tels que l'exécution de gofmt. Changer les meilleures pratiques est parfois la bonne solution. De même, vgo n'a pas besoin de gérer toutes les situations possibles impliquant des incompatibilités. Comme Russ l'a souligné lors de sa récente conférence à Gophercon Singapore , la seule solution permanente à l'incompatibilité est de travailler ensemble pour corriger l'incompatibilité et maintenir l'écosystème du package Go. Les solutions de contournement temporaires dans un outil comme vgo ou dep n'ont besoin de fonctionner que suffisamment longtemps pour donner aux développeurs le temps de résoudre le vrai problème, et vgo fait assez bien ce travail.

Nous apprécions tous les commentaires et la passion que vous avez apportés à ce problème critique. La proposition a été acceptée.

— Le comité d'examen des propositions Go

Pour ajouter un peu de couleur au dossier, les rencontres hebdomadaires avec @sdboyer ne doivent pas être vues comme une approbation. Sam a récemment commencé à écrire sur les problèmes de MVS ainsi que sur les choses qu'il aime à propos de vgo . J'ajoute ceci pour m'assurer qu'il n'y a pas de malentendu avec quelqu'un d'autre qui se présente. Si vous voulez son avis, lisez ses paroles. Mon point de vue est qu'ils contiennent une bonne quantité de désaccord avec l'approche actuelle prévue.

@mattfarina FWIW, j'ai lu cette phrase plus comme "nous sommes conscients de sa critique (comme il l'a exprimée en privé) et cela n'a pas changé notre opinion". Il est cependant regrettable que ses opinions et arguments ne soient pas publics à ce stade.

Il semble irresponsable d'accepter une proposition alors que des préoccupations fondamentales subsistent quant à l'approche. Le consensus entre l'auteur et l'expert du domaine communautaire @sdboyer semble être une norme minimale raisonnable à atteindre avant que la proposition ne soit considérée comme acceptée.

@merovius Plusieurs d'entre nous ont partagé des opinions publiquement et en privé. Un certain nombre de personnes pensent que les problèmes soulevés ont été passés sous silence (parfois grossièrement) plutôt que de recevoir des solutions suffisantes. Je commence à partager publiquement des problèmes pratiques afin que nous puissions essayer de les résoudre. Par exemple, juste aujourd'hui, je partage quelques détails sur un problème pratique ici . Remarque amusante, c'était sur la première page des nouvelles des hackers en même temps que cela était marqué comme accepté.

@peterbourgon En tant que personne qui a participé à l'enquête Go Dependency Management et qui a travaillé sur Glide où j'ai écouté les besoins des gens et essayé de faire en sorte que cela fonctionne, je peux montrer des problèmes pratiques (plutôt que de simples opinions). Autrement dit, je peux faire correspondre les désirs, les besoins et les attentes des utilisateurs aux solutions à ces problèmes. Ma préoccupation est l'inadéquation avec le chemin actuel de vgo. Il existe des besoins non satisfaits et des problèmes pragmatiques dus aux différences dans la façon dont les gens gèrent la dépendance.

Un moyen simple de commencer à apaiser mes inquiétudes est de faire en sorte que vgo fonctionne pour Kubernetes à la satisfaction de Tim Hockins.

Un moyen simple de commencer à apaiser mes inquiétudes est de faire en sorte que vgo fonctionne pour Kubernetes à la satisfaction de Tim Hockins.

Faire fonctionner vgo pour Kubernetes aujourd'hui ou faire fonctionner vgo pour Kubernetes dans les années à venir ? Si je comprends bien, l'un des désaccords de conception fondamentaux entre vgo et dep est de savoir si nous devons travailler avec l'écosystème tel qu'il existe aujourd'hui (hypothèse de dep) ou si nous pouvons orienter la communauté vers des versions étiquetées et maintenir la compatibilité (hypothèse de vgo) .

Il est donc possible que vgo ne fonctionne pas pour Kubernetes utilisant de nombreuses dépendances pendant un certain temps, jusqu'à ce que les normes de la communauté Go changent.

@mattfarina Bien sûr. Personnellement, je trouve très frustrant de décrire cela comme un "rouleau de vapeur". @sdboyer s'est largement abstenu de la discussion publique pendant des mois et il n'y a toujours pas d'arguments réels et concrets de sa part. Il avait ses raisons et c'est juste. Mais le consensus nécessite toujours une discussion et au moins en ce qui concerne le dossier public, je ne suis personnellement au courant d'aucun problème qui a été soulevé et clairement ignoré (je n'ai pas encore lu votre message, cependant).

En ce qui me concerne, toute discussion se déroulait à huis clos. Et étant donné que nous n'avons aucune information de toute façon, je considère qu'il est juste de supposer que les deux parties ont été dûment prises en considération.

@bradfitz SemVer est aujourd'hui utilisé par les packages Go, généralement en PHP, en node.js, en Rust et dans de nombreux autres langages. C'est une chose assez courante. J'ai rencontré des problèmes dans ces langues et d'autres où des packages ont rompu avec des problèmes de compatibilité SemVer. Parfois intentionnellement et parfois par accident. Que fera Go différemment pour éviter un problème présent dans toutes ces autres langues parce que les gens sont faillibles ?

Si nous ne pouvons pas exprimer cela, c'est une mauvaise hypothèse que la compatibilité sera toujours maintenue et que les développeurs ne devraient pas avoir de boutons accessibles pour régler cela et transmettre ces informations dans l'arborescence des dépendances.

Je pense que tout le monde sera d'accord : la situation actuelle avec la gestion des dépendances est horrible, dans n'importe quelle langue/plate-forme. Je crois que @bradfitz a correctement expliqué le principal point de conflit. Peut-être que vgo ne réussira pas, mais pour moi, il est évident que nous devons changer quelque chose (je veux dire pas seulement dans Go, mais en général), et vgo semble très prometteur pour l'essayer.

@mattfarina Nous prévoyons d'essayer de mettre en place un service qui contrôlera automatiquement si la compatibilité est effectivement maintenue. En l'intégrant à godoc.org, en fournissant des badges pour README, en l'utilisant comme proxy pour aller chercher - il existe de nombreuses façons d'essayer de le faire fonctionner suffisamment bien. Bien sûr, @sdboyer a raison sur le fait que la compatibilité de l'API ne garantit pas la compatibilité réelle, mais c'est un bon début et devrait fonctionner assez bien dans la plupart des cas.

Il est donc possible que vgo ne fonctionne pas pour Kubernetes utilisant de nombreuses dépendances pendant un certain temps, jusqu'à ce que les normes de la communauté Go changent.

L'espoir n'est pas une stratégie, surtout lorsque les comportements et les attentes existants sont déjà bien établis. Go aurait peut-être eu des jetons d'innovation à dépenser ici si nous avions eu cette discussion il y a cinq ans, et les choses étaient plus susceptibles d'être influencées. Mais à force d'avoir ignoré le problème pendant si longtemps, il me paraît clair que tout outillage proposé aujourd'hui doit rencontrer les utilisateurs là où ils se trouvent.

Que fera Go différemment pour éviter un problème présent dans toutes ces autres langues parce que les gens sont faillibles ?

Nous avons discuté d'une sorte de commande go release qui facilite à la fois les versions/le marquage, mais vérifie également la compatibilité de l'API (comme le vérificateur Go-interne go tool api que j'ai écrit pour les versions Go). Il peut également être en mesure d'interroger godoc.org et de trouver les appelants de votre package et d'exécuter leurs tests sur votre nouvelle version également au moment de la pré-version, avant qu'une balise ne soit poussée. etc.

trouvez les appelants de votre package et exécutez leurs tests sur votre nouvelle version également au moment de la pré-version, avant qu'une balise ne soit poussée. etc.

Ce n'est pas vraiment pratique pour quiconque n'est pas Google.

Ce n'est pas vraiment pratique pour quiconque n'est pas Google.

Avec tous les fournisseurs de cloud qui commencent à proposer des conteneurs en tant que service payants, je ne vois aucune raison pour laquelle nous ne pourrions pas fournir cela en tant qu'outil open source que n'importe qui peut exécuter et payer les 0,57 $ ou 1,34 $ dont il a besoin pour exécuter un million de tests sur un groupe d'hôtes pendant quelques minutes.

Il n'y a pas beaucoup de sauce secrète Google quand il s'agit d'exécuter des tests.

Avec tous les fournisseurs de cloud qui commencent à proposer des conteneurs en tant que service payants, je ne vois aucune raison pour laquelle nous ne pourrions pas fournir cela en tant qu'outil open source que n'importe qui peut exécuter et payer les 0,57 $ ou 1,34 $ dont il a besoin pour exécuter un million de tests sur un groupe d'hôtes pendant quelques minutes.

Cela nécessite un compte auprès d'un fournisseur de cloud spécifique, nécessite que vous acceptiez les conditions d'utilisation d'un fournisseur de cloud spécifique (ce que vous pouvez ou non être en mesure de faire pour des raisons juridiques, même si la plupart du monde traite cela comme si ce n'était pas le cas important), exige que vous viviez dans une zone desservie par le fournisseur de cloud (par exemple, si vous êtes en Iran et que le fournisseur de cloud est aux États-Unis, vous ne pourrez peut-être pas l'utiliser en raison des lois sur l'exportation), et exige que vous avez l'argent à dépenser pour payer le fournisseur de cloud (vraisemblablement chaque fois que vous faites une version). Ce n'est peut-être pas beaucoup d'argent, mais cela ne signifie pas que tout le monde pourra le payer. Si nous voulons que Go soit inclusif et utilisable par un public diversifié, cela ne semble pas être une bonne solution.

/deux centimes

@SamWhited MeteorJS a travaillé avec galaxy, une commande meteor publish intégrée pour exécuter votre projet dans un fournisseur de cloud. Peut-être que je comprends mal le problème posé, mais leur swing semblait correct.

@bradfitz Et si l'API ne change pas mais que le comportement derrière elle le fait? C'est un cas qui rompt avec SemVer et impacte ceux qui l'importent. Comment détectez-vous cette situation ? Je demande parce que je l'ai vécu plus d'une fois.

outil open source que n'importe qui peut exécuter et payer les 0,57 $ ou 1,34 $ dont il a besoin pour exécuter un million de tests sur un groupe d'hôtes pendant quelques minutes.

Cela touche maintenant au coût. Cela peut sembler bien pour les gens d'une ville technologique aux États-Unis. Qu'en est-il des personnes en Afrique, en Amérique centrale ou dans d'autres endroits qui sont répartis dans le monde entier. Comment des outils comme celui-ci sont-ils généralement accessibles en dehors des cercles de "l'élite technologique" ?

Et qu'en est-il de tous les cas où le cloud public ne fonctionne pas ? Sur site (beaucoup de gens le font) ou propriétaire et ayant des problèmes de confiance. Comment cela fonctionnera-t-il pour eux ? Si vous disposez d'un outil interne, vous ne voudrez peut-être pas divulguer aux services publics les importations que vous utilisez. Supposons que vous obteniez vos importations à partir de GitHub, mais que ce service s'exécute dans Google. Les gens se sentent-ils d'accord pour confier leur arbre de dépendance à Google ? Un groupe ne le fera pas.

Il peut également être en mesure d'interroger godoc.org et de trouver les appelants de votre package et d'exécuter leurs tests sur votre nouvelle version également au moment de la pré-version, avant qu'une balise ne soit poussée. etc.

Prenons Kubernetes comme exemple. Quelqu'un écrit un package qui est importé dans Kubernetes. Un outil doit donc obtenir cela et exécuter tous les tests. Certaines parties sont conçues pour fonctionner sous Windows et POSIX. Pouvons-nous tester multi-OS/multi-arch (puisque Go gère cela). À quoi cela va-t-il vraiment ressembler (et coûter) ?

--

Je pense que des outils comme celui-ci peuvent être utiles. Je ne veux pas dire que les gens pensent autrement. Je ne vois tout simplement pas comment ils résolvent le problème pour beaucoup de gens. Ils ne sont pas assez pratiques ou ne conviennent pas à toutes les configurations.

On a l'impression d'essayer de résoudre un problème mathématique avec des contraintes connues et contrôlables. Mais, les gens sont désordonnés, nous avons donc besoin de solutions tolérantes aux pannes.

Pour citer @technosophos plus tôt dans la journée :

"Les gestionnaires de version ne sont pas réellement des outils pour les compilateurs ou les éditeurs de liens ou quoi que ce soit... Les gestionnaires de version sont destinés aux personnes qui collaborent."

Pour ce que ça vaut, il a écrit plus d'un gestionnaire de dépendances, en a étudié d'autres et a parlé avec des gens qui en ont écrit encore plus.

Il semble irresponsable d'accepter une proposition alors que des préoccupations fondamentales subsistent quant à l'approche. Le consensus entre l'auteur et l'expert du domaine communautaire @sdboyer semble être une norme minimale raisonnable à atteindre avant que la proposition ne soit considérée comme acceptée.

Juste pour ajouter un peu ici : nous avons une histoire autour des emballages qui est à la fois non standard et sous-optimale (l'écosystème go get ). Il vaudrait mieux abandonner un gestionnaire de paquets standard plutôt que d'avoir un autre go get publié qui pousse les gens vers de mauvaises pratiques au nom de la compatibilité avec l'outil "standard". En tant que personne qui utilise Go depuis sa sortie publique, je trouve cette conversation frustrante et décourageante car il semble que la direction de l'équipe Go n'ait pas tiré les leçons des erreurs commises avec go get (née goinstall ).

Il y a des problèmes raisonnables et pratiques qui ont été soulevés à propos de cette proposition. Nous devrions modifier la proposition pour y répondre et non simplement dire : "travailler comme prévu". Si nous ne pouvons pas le faire correctement pour la version 1.11 ou 1.12 ou 1.13, nous devrions attendre que cela puisse être fait correctement. Cette proposition propose un système qui se comporte sensiblement différemment de la plupart des autres systèmes et pas dans le bon sens.

La raison motivante derrière MVS semble être que l'approche traditionnelle est NP-Complete. Je trouve que c'est une très mauvaise motivation. Lorsqu'il s'agit de problèmes NP-Complets, la question principale est : "À quelle fréquence les instances difficiles surviennent-elles ?" Avec la gestion des packages, la réponse semble être "très rarement". Nous ne devrions pas nous contenter d'une formulation de problème incomplète et inutile juste pour éviter l'étiquette NP-HARD sur le problème.

La plupart des points concrets ont été exprimés par d'autres personnes plus proches du dossier ( @sdboyer @peterbourgon @mattfarina etc...). Mon principal reproche est que nous acceptons cette proposition alors que ces points concrets n'ont pas été traités de manière adéquate.

@SamWhited , vous contestez une fonctionnalité facultative d'une conception hypothétique. L'utilisateur hypothétique qui ne fait confiance à aucun fournisseur de cloud ou qui ne peut utiliser aucun fournisseur de cloud à l'intérieur du pare-feu de son pays ou qui ne veut pas payer peut toujours exécuter des tests (ou une fraction de ceux-ci) sur sa propre machine pendant la nuit. Ou utilisez simplement la vérification de signature go release , qui vous permet d'atteindre 95 % du chemin gratuitement.

@mattfarina , @SamWhited , déplaçons la discussion vers https://github.com/golang/go/issues/25483.

@mattfarina

J'ai rencontré des problèmes dans ces langues et d'autres où des packages ont rompu avec des problèmes de compatibilité SemVer. Parfois intentionnellement et parfois par accident. Que fera Go différemment pour éviter un problème présent dans toutes ces autres langues parce que les gens sont faillibles ?

Je ne comprends toujours pas pourquoi vgo est supposé fonctionner moins bien dans ces cas que dep. Au contraire, il me semble que vgo fonctionne strictement mieux . Dans votre article de blog, vous mentionnez un problème spécifique avec helm, comme preuve de l'échec du modèle vgo. Cependant, dans le monde de vgo, il existe deux scénarios pour lesquels vgo aurait choisi d'utiliser la v1.4.0 pour grpc :

  1. Les développeurs de helm ont choisi de spécifier grpc >= v1.4.0 dans go.mod comme exigence. Dans ce cas, ils peuvent simplement annuler cette exigence et revenir ainsi à une version précédente de grpc qui leur convient.
  2. Les développeurs d'une dépendance de helm ont choisi de spécifier grpc >= v1.4.0 . Dans ce cas, dep l'aurait également installé et si helm essayait de revenir en arrière en restreignant grpc < v1.4.0 , dep devrait croasser en raison d'exigences contradictoires.

Il me semble donc que vgo résout ce problème au moins aussi bien que dep. Pendant ce temps, dans un monde profond, il existe une autre option :

  1. Les dépendances transitives de helm nécessitaient grpc >= v1.x.0 , avec quelques x < 4 , puis grpc ont publié v1.4.0 et dep a décidé d'utiliser la nouvelle version lors de l'installation, sans qu'on lui demande . Dans ce cas, la barre serait cassée et aurait besoin de se blottir pour faire une version de correction de bogues (comme décrit dans votre message), ce qui créerait du labeur. Pendant ce temps, vgo aurait simplement ignoré la nouvelle version et les choses continueraient à bien fonctionner.

J'oublie apparemment quelque chose de basique. Mais la dernière fois que j'ai demandé des éclaircissements à ce sujet sur le mou, j'ai été reporté à un hypothétique futur article de blog. D'où ma frustration, parce que je ne comprends vraiment pas d'où vient l'idée que vgo a en quelque sorte plus de problèmes avec les gens qui cassent la sémantique de leurs versions que dep n'en aurait.

Pour clarifier, il ne s'agit pas de dep . Il s'agit d'une analyse du comportement de MVS (vgo) par rapport à d'autres solutions de gestion de packages basées sur le solveur SAT (dep inclus).

Un autre exemple de Matt indique ce qui suit :

Vous êtes le développeur du module app et vous avez deux dépendances :

  • grpc [>= 1.8 ]
  • helm , qui ont la dépendance suivante :

    • grpc [>= 1.0, < 1.4] (parce que grpc a introduit un changement de rupture dans 1.4).

La plupart des gens ne connaissent pas les exigences de dépendance transitive ( helm -> grpc [>= 1.0, < 1.4]) car cela nécessiterait d'être conscient que helm se casse quand en utilisant grpc >= 1.4. Je suppose que ce n'est pas quelque chose que la majorité des gens vont se soucier de cela ou passer du temps et de l'énergie à l'enquêter.

Si vous utilisez vgo (en vous appuyant spécifiquement sur MVS), vous obtiendrez :

  • helm
  • grpc [>= 1.8 ]

Cela devrait être une combinaison invalide (puisque les exigences helm ne sont pas satisfaites) et la plupart des gestionnaires de dep donneraient un message d'erreur vous indiquant que vous avez un conflit (étant donné que helm a déclaré ses exigences dans certains format).

C'est un point critique important de MVS et vgo. Il ne veut pas permettre aux dépendances d'indiquer quand elles ont un problème avec une version spécifique pour éviter d'avoir besoin d'une résolution SAT complète . Vous pouvez vous référer aux sections Theory et Excluding Modules de l' article MVS pour plus d'explications.

MVS ne veut pas reconnaître cette possibilité (ou du moins veut restreindre la possibilité de la dicter au module actuel) sous l'hypothèse que SemVer est toujours respecté et donc ce n'est pas nécessaire, ce qui n'est pratiquement pas toujours le cas. Je me référerais à votre article sur la rétrocompatibilité pour montrer pourquoi adhérer à la rétrocompatibilité est difficile et peu pratique lorsqu'on est obligé de suivre la voie vgo.

La solution MVS est de demander au développeur du module de spécifier les versions à exclure, ignorant les connaissances qui peuvent être partagées par les auteurs des dépendances sur ces incompatibilités. Transférant ainsi la responsabilité au développeur de connaître et d' appliquer la logique alambiquée que la plupart des gestionnaires de département suivent pour déterminer quelles versions de quelles dépendances sont compatibles les unes avec les autres (c'est-à-dire une résolution SAT).

À moins que les gens ne commencent comme par magie à se conformer à SemVer, j'imaginerais installer une dépendance lors de l'utilisation de vgo pour se transformer en un exercice excentrique où après l'importation d'un module, vous devriez vérifier un fichier README pour copier la liste des versions qui ne sont pas compatibles à inclure dans votre fichier go.mod . Gardez à l'esprit que l'instruction exclude ne prend actuellement qu'une seule version.

@Merovius

Dans le billet de blog de @mattfarina , ils décrivent intentionnellement la mise à niveau de Helm vers grpc v1.4.0, c'est-à-dire l'équivalent de la mise à jour de go.mod . La question n'est pas de savoir comment dep ou vgo évitent ce problème, mais plutôt comment ils permettent à l'auteur de la bibliothèque de s'en remettre. Dans le cas de dep, ils peuvent publier un correctif qui ajoute la contrainte grpc<v1.4.0 . Pour les utilisateurs qui ne possèdent aucune autre dépendance à grpc, cela fonctionnera simplement. Si un utilisateur a déjà mis à jour la dernière version de helm et possède une autre dépendance sur grpc>=v1.4.0 , cette contrainte entraînera l'échec de sa construction ; pas idéal, mais mieux qu'un comportement d'exécution subtilement cassé.

Avec vgo , les responsables de Helm ont-ils des options équivalentes disponibles ? Si un utilisateur a mis à jour grpc vers v1.4.0 pour une raison quelconque, MVS choisira toujours [email protected] , Helm sera cassé, et il n'y a rien que les responsables de Helm puissent faire à ce sujet (sans ajuster le comportement modifié, qui est souvent long). Je ne peux pas parler pour @mattfarina , mais c'est ainsi que j'ai lu la préoccupation soulevée et c'est celle que je partage. Avec dep et des systèmes similaires, les bibliothèques intermédiaires peuvent se défendre contre (ou plus souvent, se remettre de) des violations de compatibilité avec des contraintes de limites supérieures.

@ibrasho @mattfarina

Il semble que l'un des exemples de Russ dans la conférence GopherconSG couvre un scénario très similaire (peut-être identique?).

Dans le message ci-dessus, vous dites que helm dépend de "grpc [>= 1.0, < 1.4]". Mais ce n'est pas strictement exact. Je pense que ce que vous voulez dire, c'est qu'une version spécifique de helm dépend de "grpc [>= 1.0, < 1.4]". Disons que la version de helm est 2.1.3 ; vraisemblablement cette version de helm a été publiée après grpc 1.4 (sinon elle n'aurait pas su se marquer comme étant incompatible avec grpc 1.4). Le point de Russ dans cet exposé est que la version précédente de helm (disons 2.1.2) ne se serait probablement pas (encore) marquée comme incompatible avec grpc 1.4.

En d'autres termes, une affectation satisfaisante (selon dep) aurait été helm = 2.1.2, grpc = 1.8. Dep a pu choisir correctement cette affectation de version sans erreur, car elle satisfait toutes les contraintes des versions données.

@balasanjay

La version de Helm ne change pas fondamentalement l'exemple. [email protected] peut déclarer une dépendance sur [email protected] et l'utilisateur de helm peut avoir une dépendance sur [email protected] directement ou via un autre package. Dans ce scénario, MVS échoue et installe [email protected] et [email protected]. En outre, cet exemple suppose que l'utilisateur met intentionnellement à jour [email protected] (et donc [email protected]) et peut-être même [email protected] , [email protected] , etc. avant que le problème ne soit découvert.

MVS interdit intentionnellement les exclusions des dépendances intermédiaires pour atteindre ses objectifs théoriques :

Les implications négatives (X → ¬ Y, de manière équivalente ¬ X ∨ ¬ Y : si X est installé, alors Y ne doit pas être installé) ne peuvent pas être ajoutées...

Pour cet exemple, nous devons exprimer, si X= helm>= 2.1.3 est installé alors Y= grpc>=1.4.0 ne doit pas être installé, ce que nous ne pouvons pas faire par conception.

En effet, seuls le package de niveau supérieur (en corrigeant la rupture) et les utilisateurs de niveau inférieur (en ajoutant manuellement des exclusions) ont un recours lorsque les règles de compatibilité sont enfreintes. Les intermédiaires comme Helm doivent fonctionner avec toutes les futures versions de toutes les dépendances, ce qui, pour moi, réduit considérablement la proposition de valeur de ces bibliothèques.

Cela encouragera peut-être un meilleur comportement dans les bibliothèques fortement utilisées comme grpc et aws-sdk-go, car le poids de toute rupture sera ressenti par toutes les parties et sera plus difficile à contourner. Cependant, ce n'est pas toujours aussi facile. Et si la « casse » n'était pas vraiment une casse, mais un changement de comportement légitime qui a des conséquences inattendues pour certains utilisateurs, mais qui est utile pour d'autres ? Ce genre de chose n'est pas rare et les auteurs en amont hésiteraient à juste titre à annuler un changement dans ce scénario.

Je ne pense pas avoir été aussi clair que Russ. Laissez-moi réessayer.

Initialement, l'état de deps ressemble à ceci.
Barre 2.1.2 : grpc >= 1.0

Ensuite, grpc 1.4 est publié. Les développeurs de Helm se rendent compte qu'il y a une incompatibilité, et poussent donc une nouvelle version de Helm :
Barre 2.1.3 : grpc >= 1.0, < 1.4

Je démarre une nouvelle application qui dépend de Helm et d'une nouvelle fonctionnalité de grpc (pour les besoins de la discussion). Je liste les deps suivants :
Barre >= 2.0.0
grpc >= 1.4

L'affirmation ci-dessus était que dep remarquerait le conflit inhérent et signalerait une erreur.

Mais Russ a souligné que ce n'est pas vrai, car il existe une attribution de version sans conflit. Plus précisément, dep pourrait choisir d'utiliser helm 2.1.2 et grpc 1.4. Selon dep, il s'agit d'une affectation valide, car helm 2.1. 3 est celui qui est incompatible avec grpc 1.4, alors que 2.1. 2 est compatible avec tous les grpc >= 1.0.

En d'autres termes, dep pourrait _validement_ choisir de "réparer" un conflit, en rétrogradant vers une version qui n'a pas encore enregistré le conflit. Si vous avez des versions immuables, cela semble inévitable. Par conséquent, il semble que dep gérerait également mal https://codeengineered.com/blog/2018/golang-vgo-broken-dep-tree/.

@balasanjay Bien sûr, mais finalement Helm publie la version 2.2.0 avec une nouvelle fonctionnalité intéressante que vous souhaitez, et vous essayez de mettre à niveau, puis le problème survient.

(Je suis prudemment optimiste que cela fonctionnera bien si vgo a un UX bien conçu pour faire prendre conscience aux gens que leur résultat MVS a un "conflit" de cette forme. Par "bien conçu", je veux dire qu'il encourage les gens à faire face à le problème au lieu d'être simplement d'accord avec beaucoup d'avertissements tout le temps.)

Je suis certainement d'accord qu'il y a des situations où dep détectera un conflit, mais je voulais juste être clair que ce n'est _pas_ celui présenté dans ce billet de blog (ou du moins, pas avec les exigences de version telles qu'elles sont actuellement présentées).

Et FWIW, je pense qu'il est raisonnable de remettre en question l'efficacité d'une sauvegarde si elle se brise sur un exemple relativement simple de conflit.

Pour mémoire, j'ai retrouvé l'exemple de Russ (il est à peu près identique à celui-ci, à un degré impressionnant): https://youtu.be/F8nrpe0XWRg?t=31m28s

Re : sélection de version minimale, j'ai du mal à comprendre comment résoudre la situation suivante :

Imaginez une bibliothèque populaire en mode maintenance, par exemple la v1.2.3 est sortie depuis plus d'un an sans aucun changement. De nombreuses autres bibliothèques en dépendent.
Un développeur arrive et réalise une optimisation de vitesse à faire en v1.2.3. Il accélère la fonction principale de la bibliothèque de 10 fois, sans changement d'API ! Ceci est publié en tant que v1.3.0. Plus aucun bogue n'est trouvé dans ce paquet pour l'année suivante.

Comment les personnes à charge finissent-elles par obtenir cette mise à jour ? Ils peuvent fonctionner avec la v1.2.3, mais la v1.3.0 est évidemment meilleure.

@daurnimator

Comment les personnes à charge finissent-elles par obtenir cette mise à jour ?

Chaque application devra définir 1.3.0 comme version minimale à utiliser.

Eh bien, quelle journée idiote c'est aujourd'hui! 😄

Cette proposition a été ouverte avec des discussions actives pendant plus de deux mois

Ce problème est ouvert depuis des années, et la chronologie fixée par rsc pour tout cela était assez artificiellement courte, tout bien considéré.

Il y a eu deux objections à cette proposition dont nous estimons que nous devrions parler :

  1. La proposition ne fournit pas de solution technique à tous les scénarios possibles impliquant des incompatibilités.

S'il s'agit d'une allusion aux positions que j'ai exposées à Russ, c'est une caricature trompeuse. L'une des raisons pour lesquelles il m'a fallu si longtemps pour rassembler mes réflexions sur ce sujet est que l'utilisation répétée d'arguments et de déclarations trompeurs est... franchement, déstabilisante.

Littéralement, personne ne pense que TOUS les scénarios possibles peuvent être couverts. Le problème est, et a toujours été, que MVS ne résout qu'un problème _illusoire_ (en évitant SAT), crée de _nouveaux_ problèmes à sa place qui importent beaucoup plus dans la pratique, et ne peut pas fonctionner efficacement comme une couche intermédiaire sur laquelle nous pouvons raisonnablement opérer.

Ceux-ci sont précis dans leur observation mais fonctionnent comme prévu. Les auteurs et les utilisateurs de code devront modifier certaines de leurs pratiques concernant l'utilisation et la publication de bibliothèques, tout comme les développeurs se sont adaptés à d'autres détails de Go, tels que l'exécution de gofmt.

Rien n'est aidé en banalisant le degré de changements proposés ici en les comparant à l'exécution de gofmt - peut-être l'activité la plus insensée que nous effectuons en tant que développeurs Go.

Comme Russ l'a souligné lors de son récent discours à Gophercon Singapore, la seule solution permanente à l'incompatibilité est de travailler ensemble pour corriger l'incompatibilité et maintenir l'écosystème du package Go. Les solutions de contournement temporaires dans un outil comme vgo ou dep n'ont besoin de fonctionner que suffisamment longtemps pour donner aux développeurs le temps de résoudre le vrai problème, et vgo fait assez bien ce travail.

Soyons clairs - ce qui compte, c'est la _communauté_. Nous. Les personnes qui produisent l'écosystème logiciel. Nous obtenons un meilleur écosystème en créant des outils qui nous aident à dépenser nos jetons limités dans des collaborations utiles - et non en créant des outils fragiles qui nous punissent pour avoir participé en premier lieu.

@Merovius :

J'ai été renvoyé à un hypothétique futur article de blog. D'où ma frustration, parce que je ne comprends vraiment pas d'où vient l'idée que vgo a en quelque sorte plus de problèmes avec les gens qui cassent la sémantique de leurs versions que dep n'en aurait.

Rassembler tous ces arguments prend du temps, et ce n'est pas mon travail quotidien. J'avais pour objectif de finir ce soir, mais je suis toujours sur ma dernière passe de montage. 😢Demain matin...? Rien n'est figé !

Le problème est, et a toujours été, que MVS ne résout qu'un problème illusoire (en évitant SAT), ...

Respectueusement, à mon humble avis, la solution SAT est une non-solution, donc pour moi, MVS résout un problème très réel.

À mon humble avis, la solution SAT est une non-solution, donc pour moi, MVS résout un problème très réel.

J'aimerais comprendre le raisonnement derrière cela, si possible?

Ce problème est ouvert depuis des années, et la chronologie fixée par rsc pour tout cela était assez artificiellement courte, tout bien considéré.

Je vois ici deux idées clairement contradictoires. Les enquêtes ont montré à plusieurs reprises que la gestion de la dépendance a besoin d'une solution plus tôt que plus tard. Pourtant, un délai de six mois n'est pas suffisant pour examiner et approuver une proposition.

Je comprends qu'il ne faut pas choisir la première solution à mettre en place. Mais le temps est l'un des facteurs. La contre-proposition à vgo n'est pas encore bien définie, et mettrait très probablement des années à se concrétiser. Je choisirais vgo dans Go 1.11 plutôt qu'une solution basée sur SAT super géniale dans Go 1.14 n'importe quel jour.

Cela suppose également que ce que vgo implémente est gravé dans le marbre. Pour autant que nous sachions, vgo pourrait changer considérablement au cours des fenêtres 1.12 et 1.13.

J'aimerais comprendre le raisonnement derrière cela, si possible?

C'est le même raisonnement qui sous-tend la préférence de l'expression rationnelle de Go à PCRE, c'est-à-dire. ne pas permettre à un programme de dépendre d'un algorithme ayant une complexité quadratique/exponentielle dans le pire des cas.

Nous devons garder à l'esprit que vgo remplacera simplement go get rien de plus rien d'autre. Nous devrions comparer vgo avec go get et non vgo avec quelque chose qui n'existe pas. "Le pire est le mieux" ! Concentrons-nous maintenant sur les détails de mise en œuvre.

FWIW, il est à l'OMI tout à fait possible d'introduire des limites supérieures sans avoir un solveur SAT complet - il n'est tout simplement pas possible que la solution générée soit optimale ou de garantir qu'une solution existante sera trouvée. Si besoin est, vous pouvez

  1. Permettre de spécifier des bornes supérieures
  2. Ignorez-les lors de la résolution via MVS
  3. Vérifiez la solution trouvée par rapport à toutes les limites et croassez si elle ne convient pas (c'est la principale différence : les approches traditionnelles essaieraient de trouver une solution différente à la place)

Cela signifierait alors que vous bénéficiez des avantages de MVS (un algorithme simple sans temps d'exécution pathologiques), en conservant la possibilité de marquer les incompatibilités et de les détecter de manière statique, mais vous renoncez à la garantie de toujours trouver une solution s'il en existe une. Bien que l'on puisse affirmer que la solution que vous trouveriez n'est pas réellement une solution de toute façon, car l'incompatibilité est toujours là, juste inconnue de l'algorithme.

Donc, au moins pour moi, il semblerait qu'il soit parfaitement possible de moderniser un moyen d'obtenir des limites supérieures à MVS. Je ne suis toujours pas convaincu que c'est réellement nécessaire, mais si cela s'avère être le cas, cela peut toujours être ajouté plus tard. Rendre problématique l'assertion "MVS est fondamentalement inapte". Mais je peux toujours mal comprendre le problème. Et il y a peut-être un scénario d'échec qui l'illustre mieux ?

@sdboyer Pas de soucis. Comme je l'ai dit, je comprends parfaitement que ce n'est pas votre travail quotidien et j'apprécie le temps que vous prenez pour participer. C'est toujours une question pratique de "si nous ne connaissons pas les arguments, nous ne pouvons pas en parler". Je peux imaginer que vous êtes tout aussi frustré par toute la situation que moi :)

C'est le même raisonnement qui sous-tend la préférence de l'expression rationnelle de Go à PCRE, c'est-à-dire. ne pas permettre à un programme de dépendre d'un algorithme ayant une complexité quadratique/exponentielle dans le pire des cas.

@cznic Je suis d'avis que la gestion des dépendances n'est pas seulement un problème technique, elle est étroitement liée à des contraintes et considérations sociales. Je ne suis donc pas sûr que le comparer à des expressions régulières (un problème d'implémentation purement technique) et privilégier un algorithme essentiellement basé sur la complexité temporelle soit une approche équitable.

Je vois que certaines personnes favorisent MVS parce qu'il est plus simple et plus facile de raisonner et c'est une considération compréhensible si cela résout les autres aspects du problème à résoudre.

Je me demandais si les gens avaient d'autres raisons de le préférer à un algorithme basé sur SAT.

Je me demandais si les gens avaient d'autres raisons de le préférer à un algorithme basé sur SAT.

@ibrasho MVS n'a pas besoin d'un fichier de verrouillage.

Je me demandais si les gens avaient d'autres raisons de le préférer à un algorithme basé sur SAT.

Personnellement, mes raisons sont

  1. Il unifie le fichier de verrouillage et le manifeste en un seul fichier, qui peut en grande partie être édité par ordinateur. Cela signifie moins de bruit tout en obtenant des constructions reproductibles (ou "haute fidélité") dans le cas courant. AFAICT c'est quelque chose d'unique à MVS. Comme l'une de mes principales frustrations avec les autres gestionnaires de packages est la difficulté d'avoir à modifier les fichiers manifestes, c'est énorme pour moi.
  2. Une réparation progressive sera plus facile/rendue possible. Comme je suis un fervent partisan de cette approche pour résoudre le problème du développement distribué, c'est également important pour moi.
  3. Cela peut aider l'écosystème à rester collectivement proche de HEAD pour la plupart des bibliothèques. Il s'agit en grande partie de spéculations et dépend quelque peu de l'outillage disponible. Mais si un "tout tirer vers la dernière version" est suffisamment simple, cela peut augmenter la cadence avec laquelle les nouvelles versions des bibliothèques sont testées les unes par rapport aux autres en production.
  4. Il réalise tout cela tout en préservant ou en surpassant les qualités souhaitables des autres approches, AFAICT. Les mises à niveau ne se produisent que si vous le souhaitez. Et les packages binaires continueront à se construire même si la construction de certaines de leurs dépendances est interrompue dans une nouvelle version, ce qui donne à l'auteur le temps de travailler sur un correctif.

Surtout cette dernière partie est un peu ironique. Parce que cette qualité exacte a été décrite comme extrêmement importante dans le dernier message de @sdboyer - mais à ce stade, je pense toujours que vgo est strictement meilleur à cet égard que les approches traditionnelles.

@Merovius
"Il unifie le fichier de verrouillage et le manifeste dans un seul fichier"

  • ce n'est pas tout à fait vrai car les manifestes sont effectivement dispersés dans tous vos fichiers. Les instructions d'importation agissent efficacement comme des manifestes.

@docmerlin Quand j'ai dit "manifest", je voulais dire un fichier listant tous les modules dont vous dépendez avec leurs versions appropriées (en particulier, il contient strictement plus d'informations que les instructions d'importation, sinon vous n'en auriez pas besoin). Dans le cas de vgo, ce serait go.mod , dans le cas de dep, c'est Gopkg.toml . Vous pouvez également appeler cela le fichier de configuration du solveur de dépendances. Si vous considérez un terme différent plus approprié, n'hésitez pas à le remplacer par manifeste, lorsque vous lisez mon commentaire.

Notez qu'il est assez normal qu'il y ait à la fois un fichier répertoriant toutes les dépendances et une liste d'importations explicites (qui sont un sous-ensemble potentiellement strict des dépendances) par fichier. En particulier, tous les gestionnaires de dépendance Go que je connais le font. D'autres approches utilisent également un fichier de verrouillage qui décrit des versions spécifiques et précises à utiliser pour garantir des versions reproductibles. Et la caractéristique distinctive de MVS à laquelle je faisais référence est que ce fichier n'est pas nécessaire, car il peut être dérivé de manière unique du fichier manifest/dependency-solver-config/go.mod.

(supprimé + reposté de mon compte personnel)

@cznic l'accent mis sur les classes de complexité de MVC par rapport à une approche basée sur SAT isolément n'a pas de sens (comme je pense que @sdboyer écrit quelque part - nous sommes pris à en parler car c'est l'une des rares choses que nous pouvons nommer/identifier).

La suggestion de @bradfitz dans # 25483 pour résoudre certains des problèmes liés à vgo (qui, à mon avis, est une solution initialement folle mais peut-être très pratique) consiste à exécuter les tests d'utilisateurs arbitraires de votre API avant une version. Il s'agit d'un problème NP-complet en général, mais en pratique, cela pourrait être une excellente solution (tout comme gps2).

Donc, d'une part, nous avons des algorithmes de gestion de paquets basés sur SAT, et d'autre part, nous avons un algorithme en NL qui nous oblige à faire un travail NP-complet plus tard (ou un délai d'attente, ce que ferait n'importe quel solveur SAT pratique pour les fichiers de verrouillage contradictoires).

l'accent mis sur les classes de complexité de MVC par rapport à une approche basée sur SAT isolée n'a pas de sens ...

Je ne sais pas d'où vient le terme "focus". C'est juste que s'il y a deux algorithmes disponibles, le pire des cas est quadratique ou pire et l'autre est linéaire ou mieux, j'ai choisi le dernier et j'évite le premier. Je dirais que c'est un principe, pas une focalisation.

... suggestion dans # 25483 pour répondre à certaines des préoccupations avec vgo ...

Il semble que le problème n ° 25483 ne soit pas lié à vgo. Faute de frappe?

C'est juste que s'il y a deux algorithmes disponibles, le pire des cas est quadratique ou pire et l'autre est linéaire ou meilleur, j'ai choisi le dernier et j'évite le premier.

@cznic bien sûr, généralement si deux algorithmes vous donnent les mêmes résultats, vous voulez celui avec une complexité moindre (bien que ce ne soit même pas toujours aussi simple et sec - Python utilise le tri par insertion pour les petites entrées car malgré des limites de complexité pires, il a mieux constantes + temps d'exécution jusqu'à un certain point).

Dans ce cas (algorithmes basés sur MVS par rapport à SAT), les résultats diffèrent volontairement et ont de larges conséquences. Je suggère qu'à cause de cela, vous ne pouvez pas simplement comparer la complexité algorithmique, vous devez tenir compte de leurs impacts plus larges.

On dirait que le problème #25483 n'est pas lié à vgo

La première ligne de ce numéro est un lien vers le commentaire de Brad dans ce numéro : https://github.com/golang/go/issues/24301#issuecomment -390788506 . Bien que cet outil soit utile en dehors de vgo, il semble qu'il soit largement envisagé pour atténuer certains des inconvénients de MVS (à mon avis/compréhension).

Aïe, tant de commentaires. Je vais essayer d'ajouter quelques détails et un historique pour vous aider.

Il y a quelques années, il existait un certain nombre de solutions de gestion des dépendances (par exemple, godep, glide, etc.). Pour trouver une voie à suivre, il s'est passé quelques choses :

  1. Un groupe de personnes investies et bien informées s'est réuni en comité . Notez qu'un membre de l'équipe Go de Google faisait partie de ce groupe.
  2. Un deuxième groupe de personnes qui avaient créé des gestionnaires de dépendances ou disposaient d'informations à leur sujet ont soutenu ce premier groupe.
  3. Une enquête auprès de la communauté sur les besoins et réflexions sur les outils existants (en Go et hors Go) a été réalisée . Notez que certains résultats étaient réservés aux seuls yeux du comité.
  4. Les entreprises qui utilisent Go pour la production ont été interrogées pour obtenir des détails sur leurs besoins. Les détails de ceci ne sont pas publics afin que les gens puissent parler librement.

Les données du sondage et des entrevues ont toutes été transmises au comité. Après avoir examiné les données et en avoir débattu, ils ont décidé que nous avions besoin d'une solution avec certaines fonctionnalités et ont créé une spécification . Après ce développement, on dep a commencé à répondre à ces besoins.

À Gophercon l'année dernière, il y avait un sommet des contributeurs qui comprenait des personnes investies dans la gestion des dépendances qui en parlaient. Vers la fin de ces conversations, Russ est venu à la table et a dit quelque chose comme, je peux faire mieux si je pars seul et que je construis quelque chose. Il l'a fait et est venu avec vgo. Cela a été fait séparément de la communauté.

Vgo répond-il aux besoins exprimés par les personnes lors de l'enquête et des entretiens ? D'après ce que je comprends de Russ, il n'a pas lu les résultats mais il a critiqué le processus. Cela pourrait valoir la peine que quelqu'un fasse une cartographie.

Oh, au sommet, Russ a partagé l'une des raisons pour lesquelles, à l'époque, il n'aimait pas un solveur SAT. Il voulait une solution avec moins de lignes de code parce qu'il ne voulait pas que l'équipe Go de Google soit responsable de la maintenance d'autant de code. Je m'en souviens spécifiquement parce que j'ai fait quelques comparaisons LOC entre dep, glide et d'autres outils après cela pour avoir une meilleure idée des différences.

Go est un projet détenu et géré par Google. S'il s'agit d'un problème de ressources, le Go devrait-il appartenir à une fondation et des personnes d'autres organisations devraient-elles s'en approprier ? C'est une autre façon d'ajouter des ressources pour maintenir la chaîne d'outils.

Non, #25483 n'est pas lié à vgo. Je viens de l'énumérer comme une autre sorte de chose qu'une commande d'assistance hypothétique go release pourrait faire. Mais ce serait utile à tout moment.

Mon point le plus important était que Go n'a jamais rendu super facile la création de versions de packages Go. Dans une vie antérieure, j'ai écrit http://search.cpan.org/dist/ShipIt/ pour automatiser les versions des packages Perl CPAN et cela a fait une énorme différence lorsque vous avez des outils autour de telles choses par rapport à le faire à la main.

Je n'ai mentionné qu'un hypothétique go release parce qu'on m'a demandé ce que Go pourrait faire différemment pour aider les humains à ne pas faire d'erreurs.

Le seul problème réel que je vois avec vgo semble trivial à résoudre... le problème de la version max. Si une bibliothèque rompt avec la v1.7 d'un dep, il n'y a aucun moyen de le spécifier autre qu'une exclusion... qui n'aide que jusqu'à la sortie de la v1.8, qui est probablement toujours cassée exactement de la même manière.

Il semble qu'il serait trivial d'ajouter la version max à vgo juste comme un moyen d'aider vgo à déterminer quand deux bibliothèques sont incompatibles. Si une bibliothèque dit qu'elle a besoin d'au moins v1.7 et qu'une bibliothèque dit qu'elle a besoin

Sans cela, vgo n'utilisera que la version 1.7 et l'une des bibliothèques tombera en panne. Si vous avez de la chance, il y a une erreur de compilation... plus probablement, il y a juste un bogue de comportement subtil qui pourrait ne pas être remarqué avant le début de la route. Et ce qui est insidieux, c'est qu'il s'agit probablement d'une dépendance transitive que vous n'appelez même pas directement.

Les restrictions de version @natefinch max poussent MVS hors de son territoire très intelligent de solutionneur SMT.

Je pense que @natefinch signifie des versions maximales comme vérification/filtre final. Une fois que MVS a fait son travail, vgo générerait une erreur si l'une de ces restrictions de version maximale n'était pas satisfaite. Cela ne nous fait toujours pas entrer dans le territoire des solveurs SAT.

Exactement. Il n'y a pas de solution. Il y a juste "vgo dit que 1.7 est la bonne chose à utiliser, mais le module X indique qu'il ne fonctionne pas avec cette version". C'est déjà quelque chose qui peut arriver aujourd'hui avec vgo si vous avez quelque chose qui dit require foo 1.7 et quelque chose d'autre qui dit exclude foo 1.7 , s'il n'y a pas de version foo supérieure.

Et puis qu'est-ce que tu comptes faire ?

Vous utilisez votre cerveau humain pour trouver une solution, car il n'y a pas de solution mécanique. Vous essayez d'utiliser deux bibliothèques qui déclarent catégoriquement qu'elles nécessitent des versions incompatibles d'une bibliothèque. A rompra avec 1,6, B rompra avec 1,7. La fin.

Vous devez soit convaincre l'auteur de la dépendance de corriger le bogue (s'il s'agit d'un bogue), soit convaincre l'un des auteurs de la bibliothèque de publier une nouvelle version compatible avec la nouvelle version de la dépendance, soit créer tout un tas de choses et le réparer vous-même .

Il n'y a pas de bonne réponse. Mais aucun outil au monde ne peut résoudre ce problème pour vous non plus.

@sdboyer

Le problème est, et a toujours été, que MVS ne résout qu'un problème illusoire (en évitant SAT),

Je ne peux pas parler de vos conversations privées avec Russ, mais "éviter SAT" me semble être un argument d'homme de paille. « Éviter le SAT » n'est pas plus un objectif que « utiliser le SAT » : ni l'un ni l'autre n'a d'impact concret sur les utilisateurs.

Selon moi, les problèmes concrets que MVS résout sont :

  • rendre les builds reproductibles par défaut,
  • construction aussi proche que possible des versions testées, et
  • éviter les faux rejets.

Nous obtenons un meilleur écosystème en créant des outils qui nous aident à dépenser nos jetons limités dans des collaborations utiles - et non en créant des outils fragiles qui nous punissent pour avoir participé en premier lieu.

Je suis d'accord. Mais je veux regarder de plus près vos hypothèses : quels outils « punissent » la participation et pourquoi ?

L'un des exemples que vous avez donnés dans votre message était : "Notre projet dépend actuellement de [email protected] , mais il ne fonctionne pas avec [email protected] ou plus récent. Nous voulons être de bons citoyens et nous adapter, mais nous n'avons tout simplement pas la bande passante en ce moment.


La première hypothèse (implicite) que vous faites est que vous (ou vos utilisateurs) avez eu le temps et la bande passante nécessaires pour tester votre projet de manière exhaustive par rapport à toutes les versions de ses dépendances.¹ Pour certains projets, cette hypothèse en elle-même peut ne pas tenir : en s'attendant à ce que tout le monde marque des limites supérieures lorsqu'il découvre des incompatibilités, vous finissez par "punir" les responsables qui n'ont pas la bande passante pour tester les régressions et mettre à jour les limites sur potentiellement toutes leurs versions.

En revanche, sous MVS, les mainteneurs ne sont obligés de déclarer qu'une seule chose : "Nous avons testé minutieusement contre [email protected] et cela a fonctionné." Si vos utilisateurs ne font rien pour perturber cela, ils construisent contre [email protected] et tout continue à fonctionner comme avant.

Sous MVS, _rupture ne se produit qu'au moment d'une mise à niveau explicite._ C'est un avantage significatif : si votre utilisateur met à niveau une autre dépendance afin qu'elle récupère [email protected] et interrompe son utilisation de votre package, alors il peut simplement annulez cette mise à niveau jusqu'à ce que vous ayez le temps de la réparer, _ou jusqu'à ce que le mainteneur de X ait le temps de corriger l'incompatibilité._ Et étant donné les bonnes attentes, cette dernière peut être beaucoup plus probable que la première : [email protected] peut s'avérer inutile si [email protected] restaure la compatibilité.


La deuxième hypothèse que vous faites est que chaque incompatibilité qui affecte _n'importe quelle partie_ de votre module affecte _tous les utilisateurs_ de votre module. Si la partie de votre package qui tombe sous [email protected] est une fonction peu utilisée, pourquoi empêcher vos utilisateurs de mettre à jour X dans leur programme qui ne l'appelle même pas ?

Vous pourriez dire que si certaines parties du module ne dépendent pas d'autres parties, elles devraient être des modules séparés, mais cela oblige à nouveau un travail supplémentaire aux mainteneurs de paquets : si je n'ai que la bande passante pour tester et mettre à jour périodiquement, je n'aurai peut-être que la bande passante pour maintenir un module, pas tout un complexe de modules à granularité fine avec des dépendances à granularité fine.


¹ En général, la détection d'incompatibilités avec des dépendances nécessite que vous testiez par rapport au _produit croisé de toutes les versions_ de ces dépendances : il est possible que votre utilisation particulière de [email protected] soit correcte, mais elle se casse en combinaison avec un autre paquet dont vous dépendez au. Par exemple, vous et votre dépendance avez peut-être besoin d'options incompatibles dans une configuration globale.

ils peuvent simplement annuler cette mise à niveau

Cela suppose qu'il s'agit d'une erreur de compilation ou de quelque chose de similaire très visible. Il est beaucoup plus probable qu'il s'agisse d'un bug de comportement subtil qui n'est pas immédiatement apparent. Vous mettez à jour, exécutez vos tests et tout semble bon. Peut-être qu'un délai d'attente qui était de 10 secondes est maintenant de 30, et cela annule les délais d'attente dans le reste de votre pile lorsqu'il est sous charge. Vous ne le remarquerez pas tant qu'il ne sera pas en production (quelque chose de similaire nous est arrivé avec un changement de mgo il y a quelques années).

Si la partie de votre package qui casse sous [email protected] est une fonction peu utilisée, pourquoi empêcher vos utilisateurs de mettre à jour X dans leur programme qui ne l'appelle même pas ?

Parce qu'ils ne sauront probablement pas s'ils utilisent ou non cette fonction s'il s'agit d'une dépendance transitive, et qui peut dire qu'un chemin de code inutilisé ne sera pas soudainement activé lorsque vous modifierez votre code ? Donc, cette fonction cassée est maintenant appelée. Il est de loin préférable de faire confiance au responsable de la bibliothèque qui est un expert dans la compréhension de sa propre bibliothèque, que s'il dit que cela ne fonctionne pas avec 1.7, ne construisez pas avec 1.7.

Cela suppose qu'il s'agit d'une erreur de compilation ou de quelque chose de similaire très visible. Il est beaucoup plus probable qu'il s'agisse d'un bug de comportement subtil qui n'est pas immédiatement apparent.

Il y a des bogues subtils qui se cachent dans presque toutes les versions de presque tous les logiciels. Nous ne marquons généralement pas les versions comme complètement inutilisables simplement parce que nous avons trouvé un bogue de ce type ; à la place, nous le corrigeons dans une version ultérieure.

Qu'est-ce qui rend cette classe particulière de bogue spéciale ?

qui peut dire qu'un chemin de code inutilisé ne sera pas soudainement activé lorsque vous modifierez votre code ?

C'est exactement l'argument MVS : si vous modifiez votre code, vous détectez la rupture _à cette révision,_ et vous pouvez également mettre à jour la contrainte de version à cette révision.

Cela implique qu'en tant qu'utilisateur, il est plus facile de diviser les échecs si vous mettez à niveau vos dépendances une à la fois plutôt qu'en masse, mais c'est vrai pour les changements en général : plus vos changements sont petits, plus vous pouvez coupez-les en deux, qu'il s'agisse de modifications de votre code ou de ses dépendances.

Qu'est-ce qui rend cette classe particulière de bogue spéciale ?

Ce n'est pas qu'un bug. C'est plus grand que ça. L'auteur de la bibliothèque, qui est le plus grand expert de leur code, a dit au monde "yo, la version 1.7 de X casse mes trucs d'une manière si mauvaise, ne construisez même pas avec".

De toute évidence, à moins qu'il ne s'agisse d'une erreur de compilation, c'est un appel au jugement. Si 99 de vos fonctions paniquent, mais pas une... est-ce juste un bogue ? Ou est-ce une incompatibilité totale ? Et si c'est juste une fonction qui panique ?

À un moment donné, un humain doit prendre cette décision. Je préférerais de loin traiter une incompatibilité déclarée préventive qui se produit au moment de la construction, plutôt que de m'inquiéter d'un problème majeur non déclaré le mettant en production.

Ce n'est pas qu'un bug. C'est plus grand que ça. L'auteur de la bibliothèque, qui est le plus grand expert de leur code, a dit au monde "yo, la version 1.7 de X casse mes trucs d'une manière si mauvaise, ne construisez même pas avec".

Il existe une autre façon pour un auteur de bibliothèque d'exprimer cela : écrivez un test qui échoue lorsqu'il est utilisé avec une version incompatible de X. Cela aura l'avantage de ne nécessiter aucune modification de la bibliothèque si X publie une version corrigée, ainsi que de détecter tout futures régressions.

Écrivez un test qui échoue lorsqu'il est utilisé avec une version incompatible de X.

Ouais, j'y ai pensé. Mais ensuite, vous demandez à chaque binaire de niveau supérieur d'exécuter tous les tests pour toutes les dépendances transitives, des tests qui peuvent nécessiter une infrastructure que vous n'avez pas. Toutes les suites de tests ne sont pas isolées à 100 %.

Il y a une raison pour laquelle go test ./... n'exécute pas de tests dans le répertoire du fournisseur.

Pour résumer (probablement mal), il semble que le principal argument technique contre vgo est qu'il doit y avoir un moyen pour les bibliothèques de déclarer des contraintes globalement respectées sur leurs propres dépendances.

Pourquoi ne pas faire en sorte que les deux parties acceptent de sanctionner une proposition concurrente qui explore comment GPS2 pourrait s'intégrer aux parties de vgo que les deux parties aiment. Ensuite, fusionner l'expérience vgo en attendant et revoir la proposition GPS2 avant que vgo ne fusionne la ligne principale ?

En tant que personne qui a lutté avec de nombreux outils de dépendance dans le passé, je suis enthousiasmé par vgo. FWIW, en tant que membre de la "communauté", je me sens bien représenté par la solution vgo jusqu'à présent. Cependant, je reste ouvert à l'examen des arguments en faveur de l'ajout de contraintes de version globales et j'ai hâte que cet argument se développe davantage.

Juste jeter ça là-bas:

Cela suppose qu'il s'agit d'une erreur de compilation ou de quelque chose de similaire très visible. Il est beaucoup plus probable qu'il s'agisse d'un bug de comportement subtil qui n'est pas immédiatement apparent. Vous mettez à jour, exécutez vos tests et tout semble bon. Peut-être qu'un délai d'attente qui était de 10 secondes est maintenant de 30, et cela annule les délais d'attente dans le reste de votre pile lorsqu'il est sous charge.

C'est un problème dans les logiciels en général. NPM (l'autre outil de versioning avec lequel je suis personnellement le plus familier) utilise un solveur SAT combiné à une communauté qui a fortement adopté semver, et ce problème existe toujours.

En ce qui concerne la discussion sur les dépendances transitives, la réalité est qu'il n'y a pas de baguette magique : à un moment donné, le développeur doit être conscient des dépendances qu'il utilise et prendre le temps de tester correctement le code dont il est finalement responsable. Mon employeur ne peut pas être le seul où nous sommes tenus de justifier chaque bibliothèque que nous utilisons, y compris les bibliothèques transitives, pour des raisons juridiques et autres.

Honnêtement, à mes yeux, beaucoup de plaintes envers vgo semblent être "ce n'est pas parfait, donc ça ne marchera pas". N'échouons pas à mettre en place une bonne solution faute d'une solution parfaite.

Pour moi, cela semble très conforme à la philosophie globale de Go pour l'équipe principale de fournir un outil qui est bon dans la plupart des situations, laissant à la communauté le soin de fournir des outils plus avancés et/ou spécifiques.

@malexdev Il peut y avoir un problème avec vos acteurs dans l'argument selon lequel :

N'échouons pas à mettre en place une bonne solution faute d'une solution parfaite.

dep est une bonne solution aujourd'hui. Celui qui a été créé par la communauté travaillant ensemble. vgo, comme commencé plus tôt, fait quelques hypothèses :

  1. Que personne ne rompra jamais avec Semver, même par accident
  2. Que nous devrons retravailler les bases de code existantes dans l'écosystème existant

vgo est plus basé sur la "solution parfaite" dans un "monde parfait" tandis que dep fonctionne aujourd'hui en suivant ce qui fonctionne déjà dans d'autres écosystèmes de langages de programmation tout en étant tolérant aux pannes.

Vous pouvez le voir dans l' historique de l'espace des problèmes de gestion des paquets que je viens d'écrire .

Pour résumer (probablement mal), il semble que le principal argument technique contre vgo est qu'il doit y avoir un moyen pour les bibliothèques de déclarer des contraintes globalement respectées sur leurs propres dépendances.

Je suis d'accord avec ce résumé.

Pourquoi ne pas faire en sorte que les deux parties acceptent de sanctionner une proposition concurrente qui explore comment GPS2 pourrait s'intégrer aux parties de vgo que les deux parties aiment.

À ce stade, je ne suis toujours pas convaincu que le GPS2 soit une nécessité ou même une bonne idée. La capacité que vous avez indiquée ci-dessus peut être adaptée à vgo au-dessus de MVS (comme this ou this ). Personnellement, j'espère que le prochain article de blog de @sdboyer contiendra de bons arguments contre MVS lui-même, mais pour le moment, je ne vois vraiment aucune raison pour un algorithme différent - en particulier un qui coûterait des avantages UX significatifs à vgo.

Bien que, pour être juste, je ne vois aucune raison de ne pas expérimenter cela.

dep est une bonne solution aujourd'hui.

Je ne suis pas sûr d'être d'accord. Je ne l'ai pas utilisé moi-même, mais là où plusieurs personnes se plaignent de problèmes qui semblent directement liés à son approche de résolution SAT. Et je sais que je suis très mécontent de la conception globale de Deps (laissant de côté la question du solveur de dépendances lui-même, donc du flux de travail général et de l'UX).

  1. Que personne ne rompra jamais avec Semver, même par accident

Je suis désolé, mais j'ai demandé à plusieurs reprises une justification de cette déclaration et je n'en ai pas obtenu. Pourquoi vgo supposerait-il cela de quelque manière que ce soit, forme ou forme plus que dep ? Je suis fondamentalement en désaccord avec cette affirmation. C'est une hypothèse faite pour expliquer l'algorithme. Tout comme si vous expliquiez l'algorithme de dep, vous expliqueriez les hypothèses intégrées aux versions sémantiques. Au pire, ils affichent les mêmes ruptures si vous ne respectez pas cette sémantique.


Je pense qu'en général, il est logique de faire la distinction entre les différents éléments de ce dont nous parlons. Certaines des plaintes concernent SIV, certains MVS et d'autres le vgo-shell général. Par exemple, il est vrai que MVS ne peut pas gérer les limites de version supérieures, mais cela ne signifie pas que vgo ne peut pas gérer les limites de version supérieures. SIV nécessite de changer beaucoup de code (en réécrivant les instructions d'importation), mais encore une fois, cela ne signifie même pas nécessairement que vgo l'exigerait. Bien que pour être clair, je ne pense pas non plus que ce soit si grave, tant que nous pouvons migrer. Quel AFAICT nous pouvons.

Je viens de regarder le discours d'ouverture de GopherConSG de @rsc sur la gestion des versions. Il a abordé le scénario dans lequel une dépendance introduit un changement avec rupture et a comparé la façon dont vgo et dep le géreraient, ce qui semble être la principale préoccupation ici. (C'est une super montre.)

Si j'ai bien compris son point de vue, dep peut également casser la construction si une limitation de version maximale est utilisée pour éviter une mauvaise version . Je serais très intéressé de voir ce point abordé par ceux ici qui craignent que vgo ne soit pas à la hauteur à cet égard.

@willfaught Pour nous, briser la construction lorsqu'une limitation de version maximale est utilisée pour éviter une mauvaise version est considéré comme un succès ! C'est ce que nous voulons qu'il se passe. Russ note correctement que ce problème n'est pas résolu automatiquement. Une contrainte sur Helm>2.0.0 ne va pas automatiquement mettre à niveau l'utilisateur vers " [email protected] " mais cela fonctionnerait avec succès (rétrograder grpc ou déclencher un échec de construction si c'est impossible) si l'utilisateur dépendait explicitement de " Helm ==2.1.4". Personnellement, la première chose que j'essaie habituellement lorsque je rencontre un problème avec une bibliothèque est de forcer une mise à jour vers la dernière version. Avec Dep, cela m'informerait de l'échec introduit par GRPC 1.4.0. Avec vgo , le seul moyen pour Helm de me le communiquer est par le biais de la documentation.

Pour répéter le point parce qu'il continue à ne pas être compris : ni dep ni vgo ne peuvent empêcher ce problème de se produire ou fournir une solution infaillible. Plutôt, dep permet à Helm de communiquer que le problème existe, alors que vgo ne le fait pas.

Pour résumer (probablement mal), il semble que le principal argument technique contre vgo est qu'il doit y avoir un moyen pour les bibliothèques de déclarer des contraintes globalement respectées sur leurs propres dépendances.

J'ajouterais de la couleur à ce résumé dans la mesure où ces contraintes sont nécessaires pour faire face au chemin malheureux de la violation des règles de compatibilité. vgo établit la règle de compatibilité d'importation, puis procède au développement d'une solution en supposant que cette règle est toujours suivie. Dans ce monde idéalisé, le besoin de bornes supérieures est limité voire inexistant. Dans le monde réel, cela n'arrivera pas : les développeurs publieront des mises à jour qui rompent la compatibilité, intentionnellement ou non.

Je pense que @Merovius est sur une solution viable. MVS procéderait comme spécifié, puis une fois la résolution terminée, vgo vérifierait chaque package résolu pour les exclusions. Si elles sont trouvées, elles sont signalées à l'utilisateur final, qui peut choisir soit de modifier leurs dépendances afin de respecter ces contraintes, soit de remplacer et d'ignorer les contraintes. J'ai aussi été sur le revers de la médaille et parfois vous savez mieux que le mainteneur; cela fonctionne pour votre application et c'est tout ce qui vous intéresse.

Cela restaure un chemin permettant aux bibliothèques intermédiaires de communiquer une incompatibilité aux utilisateurs finaux. Pour répéter l'exemple de la barre encore une fois :

[email protected] : Barre @2.1.2
[email protected] : GRPC @1.3.5

==> L'utilisateur met intentionnellement à niveau [email protected] .

Utilisateur : Helm @2.1.3, [email protected] ("Helm mis à jour, je peux enfin utiliser grpc 1.4 !")
Barre : GRPC @1.4.0

==> Bug détecté ! L'utilisateur rencontre des problèmes avec Helm, alors recherchez une nouvelle version.

Utilisateur : [email protected] , [email protected]
Barre : GRPC @1.3.5, GRPC faible <1.4.0

L'utilisateur voit un avertissement indiquant que GRPC 1.4.0 est rejeté par l'installation de [email protected]. Étant donné que Helm est cassé pour moi et que c'est ce que j'essaie de réparer, je supprime ma dépendance à GRPC 1.4.0 (perdant malheureusement certaines fonctionnalités utiles) et relance MVS. Cette fois, MVS résout GRPC en 1.3.5 et Helm en 2.1.4, revérifie toutes les contraintes faibles, trouve qu'elles tiennent, et j'ai terminé.

Je ne m'attends à aucun outil pour résoudre ces problèmes comme par magie, mais je m'attends à un recours en tant que bibliothèque middleware. Pour autant que je sache, la seule option dans vgo est de bifurquer et de renommer toutes mes dépendances en amont (ou de manière équivalente, de les copier dans mon projet) si je veux isoler mes utilisateurs des problèmes de compatibilité avec ces dépendances. Je pense que personne ne veut ça.

@willfaught Pour nous, briser la construction lorsqu'une limitation de version maximale est utilisée pour éviter une mauvaise version est considéré comme un succès ! C'est ce que nous voulons qu'il se passe.

Le point soulevé dans l'exposé est que vgo n'est pas pire que dep dans ce scénario. Dans son exemple , la construction n'est pas cassée dans le sens où dep ne peut pas trouver de solution ; il est cassé dans le sens où dep trouve une solution, et cette solution inclut la mauvaise version, ce qui entraîne la même mauvaise situation que nous voulions éviter.

Vous devriez vraiment voir la vidéo, qui présente un excellent exemple, mais voici l'essentiel tel que je l'ai compris/m'en souviens :

  • Les versions de package (y compris leurs exigences de dépendance) sont immuables
  • Pour ajouter une limitation de version maximale à une dépendance existante pour votre package, vous devez publier une nouvelle version de votre package.
  • Il est possible que dep choisisse la version précédente de votre package afin de satisfaire à toutes les exigences, auquel cas votre nouvelle limitation de version maximale ne sera pas présente. Cela permet d'utiliser la mauvaise version après tout.

Je suis majoritairement d'accord avec la proposition d'ajouter un maximum d'exclusions de versions, mais j'ai ce souci : supposons que je mette dans ma bibliothèque "use gRPC >1.4, <1.8" puis dans gRPC 1.9, les auteurs décident, "vous savez quoi, Helm était c'est vrai, nous avons fait un changement radical dans la version 1.8, nous revenons à notre comportement antérieur dans la version 1.9.0." Désormais, les personnes essayant d'importer Helm + gRPC ne pourront pas utiliser 1.9 jusqu'à ce que Helm publie une version indiquant "utilisez gRPC> 1.4, sauf 1.8.0, 1.8.1, 1.8.2, mais 1.9+ est cool".

En d'autres termes, peut-être exclude grpc 1.8 est suffisant car nous ne saurons pas si gRPC 1.9 sera incompatible ou non tant qu'il ne sera pas publié, auquel cas Helm pourra l'ajouter ou non à la liste d'exclusion.

Je ne sais pratiquement rien de cet espace. Mais à la lecture de la discussion ici, il semble que le plus grand désaccord se résume à la façon de détecter les cas erronés. Autrement dit, MVS (vgo) et SAT (dep) gèrent plus ou moins bien les situations normales, peut-être pas de manière identique, mais assez bien.

SAT fournit une capacité que MVS n'offre pas : en utilisant SAT, l'auteur du package de bibliothèque P1 peut déclarer "P1 nécessite P2 et fonctionne avec P2Version > 1.1 et P2Version < 1.4". MVS ne peut déclarer que "P1 requiert P2 et fonctionne avec P2Version > 1.1", et ne peut pas exprimer la restriction "P2Version < 1.4". Dans le cas normal, cela n'a pas d'importance. Cela n'a d'importance que si une opération tente de mettre à niveau P2 vers la version 1.4. Dans ce cas, SAT signalera une erreur, contrairement à MVS. Lors de l'utilisation de MVS, si l'incompatibilité n'est pas une erreur de compilation, cela peut provoquer un échec longtemps après coup.

Sans aucun doute, les partisans de la SAT voient d'autres problèmes majeurs avec MVS, mais jusqu'à présent, c'est celui que je comprends.

Je pense qu'il convient de noter que si les expressions de restriction sont elles-mêmes versionnées - si elles font partie d'une version spécifique de P1 - alors dans le cours normal des événements, avant la sortie de la version 1.4 de P2, la version 2.2 de P1 dira avec plaisir "P2Version > 1.1". Ce n'est que lorsque la version 1.4 de P2 sera publiée que les auteurs de P1 remarqueront l'incompatibilité et publieront la version 2.3 de P1 avec "P2Version > 1.1 et P2Version < 1.4". Ainsi, si vous utilisez P1 version 2.2, ni SAT ni MVS ne signaleront de problème lors de la mise à niveau de P2 vers la version 1.4, même si cela échouera de manière éventuellement subtile.

En d'autres termes, s'il est parfaitement logique qu'une version de P1 répertorie les versions compatibles minimales de P2, si la version fonctionne correctement avec la version la plus récente de P2, il n'est pas logique qu'une version répertorie les versions compatibles maximales. . La version compatible maximale sera soit conservatrice, et donc de plus en plus erronée à mesure que de nouvelles et meilleures versions de P2 apparaissent, ou si P2 change d'une manière incompatible à l'avenir, ne parviendra pas à spécifier cette exigence car au moment de la sortie, elle ne le fait pas. t exister.

Donc, si nous voulons avoir un système qui définit autre chose que les exigences de version minimales, ces exigences ne doivent pas faire partie d'une version spécifique, mais doivent plutôt faire partie d'une sorte de métadonnées associées au paquet, métadonnées qui peuvent être récupérées à à tout moment sans mettre à jour le package lui-même. Et cela signifie que l'opération "mettre à jour ce package" doit être distincte de l'opération "vérifier si mes versions de package actuelles sont compatibles".

Je dirais en outre - et c'est certainement plus ténu que ce qui précède - que si "vérifier si mes versions de package actuelles sont compatibles" échoue, il est en général imprudent de faire confiance à un outil pour résoudre le problème. Si le problème de compatibilité ne peut pas être résolu par la simple opération "mettre à niveau chaque package concerné vers la version actuelle", cela nécessite une réflexion. Un outil peut guider dans cette réflexion, mais en général il ne peut pas la remplacer. En particulier, il semble très imprudent pour un outil de commencer automatiquement à rétrograder les packages.

Donc, si nous pensons en termes de

  1. un moyen de définir des métadonnées de package décrivant les incompatibilités de package
  2. sur cette base, un outil qui indique si vos packages actuels sont compatibles

alors peut-être que certaines des principales différences entre MVS et SAT deviennent moins importantes.

Merci d'avoir si bien dit Ian. Pour continuer, une fois que nous avons établi les versions et vgo, nous voulons absolument avoir un nouveau godoc.org (peut-être un nom différent) qui enregistre des informations supplémentaires sur les packages, informations que la commande go peut consulter. Et certaines de ces informations seraient une incompatibilité par paires que la commande go pourrait signaler comme des avertissements ou des erreurs dans une version particulière (c'est-à-dire, signaler les dommages, ne pas essayer de les cacher en les contournant). Mais avoir des versions dans la chaîne d'outils principale est la première étape, et c'est ce qui a été accepté dans ce numéro, avec des exigences de version minimales et une gestion des versions d'importation sémantique.


Nous nous engageons à l'atterrir le plus en douceur possible. Cela nécessitera des outils supplémentaires, plus de sensibilisation et des relations publiques pour résoudre les problèmes des packages existants. Tout cela s'est bloqué sur l'acceptation de cette proposition, car il paraissait présomptueux d'avancer sans que l'approche globale soit acceptée. Mais la proposition est acceptée et les travaux commenceront à atterrir plus agressivement maintenant que l'incertitude est passée.

J'ai eu la même pensée à propos des informations externes pour la compatibilité des versions... puisque la compatibilité des versions doit être constante, elle n'a pas besoin d'être dans le contrôle de source (et en fait, être dans le contrôle de source est un inconvénient certain, comme indiqué ci-dessus). Ce serait bien s'il y avait une solution proposée pour cela, car cela semble définitivement être le seul problème majeur avec MVS tel que proposé.

C'est génial de voir la discussion évoluer de manière organique dans cette direction. Cela a été l'un des axes centraux de mes préoccupations, et il est tellement plus facile d'expliquer les problèmes fondamentaux lorsque les gens y sont déjà presque.

@ianlancetaylor , je pense que vous avez raison avec cette observation sur la nécessité de pouvoir apporter des modifications aux informations de contrainte sur les versions déjà publiées. Comme @rsc l'a indiqué, un tel service est quelque chose dont nous avons discuté/j'ai suggéré lors de nos réunions. Nous pourrions le faire avec godoc.org, ou autre chose, bien sûr. Mais je ne pense pas qu'il s'agisse d'un service séparé, et ce serait mieux sans. J'ai fait une référence rapide à cela dans l'article que j'ai publié vendredi (juste à partir de cette ancre). Si rien d'autre, dans un service, il y a des questions auxquelles il faut alors répondre pour savoir quelle déclaration d'incompatibilités doit apparaître dans les avertissements, ce qui signifie gérer l'identité, et comment nous étendons les déclarations à des situations particulières dans le depgraph. Garder les déclarations dans des fichiers de métadonnées signifie que nous n'avons pas à nous en soucier. Mais plus à ce sujet dans une seconde.

Ce qui est vraiment important ici, c'est ce point, mais peut-être pas comme vous l'aviez prévu :

peut-être que certaines des principales différences entre MVS et SAT deviennent moins importantes.

La suggestion d'un méta-outil qui effectue cette recherche - oui, c'est une recherche SAT - comme solution aux problèmes que les gens identifient est révélatrice. C'est à peu près exactement ce que nous devrons transformer en profondeur, si MVS continue comme décrit. Et la première chose à noter ici est que, si nous sommes tellement préoccupés par ces incompatibilités que nous parlons d'un outil de recherche, alors ce que nous disons en fait, c'est que MVS devient juste une étape dans un algorithme plus large, et le Les avantages de la grokkabilité passent par la fenêtre.

Sauf que c'est pire que cela, car aucune quantité de méta-outils ne peut contourner le problème de perte d'informations qui découle du compactage des versions minimale et actuelle ensemble. Le grand résultat de cela est des restaurations en cascade , ce qui signifie qu'essayer de remédier à l'une des incompatibilités de cette liste finira très probablement par rejeter d'autres parties du graphique de dépendance qui ne sont pas nécessairement liées à votre problème. De plus, les développeurs ne pourront pas suivre une stratégie de mise à jour qui ne nuit pas aux autres. . (Oh, et les règles fantômes , mais ce n'est qu'un effet secondaire de MVS en général).

C'est pourquoi j'ai affirmé que MVS est une couche intermédiaire inadaptée sur laquelle construire un outil d'ordre supérieur comme celui-ci - "pas adapté à l'usage". Il est clair que les gens croient que ces incompatibilités se produiront, donc MVS prend juste un problème difficile et le rend plus difficile.

Si au lieu de cela, nous unifions le problème d'un "service d'incompatibilité" dans un fichier de métadonnées, alors je pense qu'il est possible , en utilisant uniquement un simple ensemble de déclarations par paires, d'obtenir le même effet. (Ceci est une ébauche du concept, mais il semble de plus en plus s'accrocher)

Cela impliquerait que certaines parties de MVS changent, mais MVS pourrait toujours fonctionner au-dessus des informations qui y sont encodées. Cela serait surtout utile si les incompatibilités deviennent vraiment folles et que vous voulez simplement les éviter toutes. Mais l'algorithme principal partirait d'une ligne de base qui ressemble à MVS, puis passerait à une recherche plus large (pour être clair, MVS lui-même devrait toujours être considéré comme une recherche), sans possibilité de passer à des versions absurdement anciennes.

(attention, je serai en vacances cette semaine, donc je ne répondrai pas avant le week-end prochain)

@sdboyer

La suggestion d'un méta-outil qui effectue cette recherche - oui, c'est une recherche SAT

Peux-tu être plus précis? La phrase que vous avez citée est juste après que Ian ait suggéré un outil pour signaler si les versions sélectionnées sont compatibles - et à ma connaissance, c'est la principale alternative suggérée ici (c'est certainement ce que je voulais dire ci-dessus). Ce problème n'est certainement pas une recherche et il est trivial et ne nécessite pas de résoudre SAT (il s'agit simplement d'évaluer une formule booléenne pour un ensemble de valeurs donné, sans essayer de trouver des valeurs qui le satisfont).

D'accord, le simple fait de signaler qu'il existe des valeurs incompatibles connues dans la formule ne nécessite pas de résoudre SAT. Prendre n'importe quelle action sur cette base, comme pour un outil qui aide à trouver un résultat sans ces valeurs.

J'ai cité cette phrase non pas parce que je pense qu'elle indique que les personnes ont accepté la recherche comme toujours nécessaire, mais parce que si nous pensons qu'il est important de signaler ces conditions, c'est parce que nous pensons qu'il est probable que nous rencontrons de tels scénarios.

le problème est qu'une fois que la plausibilité et l'importance de traiter ces cas sont établies, il semble que les gens font alors le saut erroné que "nous pouvons simplement faire toutes les choses de recherche sur MVS, et tout ira bien". nous le pouvons, mais de telles tentatives deviennent beaucoup plus délicates à gérer en raison des chemins possibles utiles que MVS coupe, par conception.

Le 28 mai 2018 à 16:02:13 HAE, Axel Wagner [email protected] a écrit :

@sdboyer

La suggestion d'un méta-outil qui effectue cette recherche - oui, c'est un
Recherche SAT

Peux-tu être plus précis? La phrase que vous avez citée est juste après Ian
proposer un outil pour signaler si les versions sélectionnées sontcompatible - et à ma connaissance, c'est le principal
alternative suggérée ici (c'est certainement ce que je voulais dire ci-dessus).
Ce problème n'est certainement pas une recherche et c'est trivial et
ne nécessite pas de résoudre SAT (il s'agit simplement d'évaluer une formule booléenne
pour un ensemble de valeurs donné, sans essayer de trouver des valeurs qui le satisfassent).

--
Vous recevez ceci parce que vous avez été mentionné.
Répondez directement à cet e-mail ou consultez-le sur GitHub :
https://github.com/golang/go/issues/24301#issuecomment -392595150

J'ai cité cette phrase non pas parce que je pense qu'elle indique que les personnes ont accepté la recherche comme toujours nécessaire, mais parce que si nous pensons qu'il est important de signaler ces conditions, c'est parce que nous pensons qu'il est probable que nous rencontrons de tels scénarios.

Pour être clair : la suggestion de moderniser les limites supérieures de cette manière est purement réactive aux préoccupations soulevées et montre que cela peut être fait (pour remettre en question de manière critique l'affirmation selon laquelle le MVS est fondamentalement inadapté). Il semble un peu injuste de prendre cette concession et cette volonté de compromis comme preuve que nous pensons que vous aviez raison depuis le début.

Pour moi, cette affirmation (que MVS est inapte et constitue un pas essentiellement irréversible dans la mauvaise direction) est ce que je conteste personnellement et la lentille à travers laquelle je lis vos arguments. L'un de ces arguments était que c'est une fonctionnalité si nous pouvons déclarer des incompatibilités et faire échouer l'algorithme de sélection de version lorsqu'elles sont rencontrées. Un autre argument juste est que s'ils se produisent, ce serait bien que l'algorithme soit capable de les résoudre pour nous (ce qui nécessiterait en effet un solveur SAT).

Cependant, même si je pense que ce sont des préoccupations valables et justes, je ne pense pas qu'elles me prouvent que MVS est fondamentalement inapte. Je crois toujours que MVS en tant que point de départ apporte de bonnes et importantes fonctionnalités à la table. Et que si ces préoccupations s'avèrent causer une douleur importante dans la pratique, il existe encore de nombreuses façons d'itérer à ce sujet - en ajoutant des limites supérieures (que ce soit dans le cadre de go.mod ou en tant que service séparé) avec des échecs purs jusqu'à et y compris l'ajout d'un solveur SAT complet et de verrouiller les fichiers à un moment donné. C'est-à-dire que je suis d'accord avec vous que ces choses vont arriver, mais a) je suis (peut-être naïvement) optimiste qu'elles ne causeront pas autant de douleur que vous le prévoyez et b) qu'il s'agit de problèmes résolubles même lorsque nous commençons avec MVS.

Il me vient à l'esprit que quelque chose en dehors du contrôle de source déterminant la compatibilité changerait le déterminisme d'un système MVS. Si vous avez foo >= 1.5.0 comme contrainte dans une bibliothèque, et une autre bibliothèque a foo >= 1.6.0. Ensuite, mettez ces deux dans un binaire et ils choisissent 1.6.0. Dans MVS, c'est tout ce dont vous avez besoin pour une construction reproductible. il choisira toujours 1.6

Mais si vous ajoutez une compatibilité externe au mélange, vous pouvez mettre à jour cette première bibliothèque pour dire qu'elle n'est pas compatible avec 1.6, puis l'algorithme choisira 1.7, même si le code n'a pas changé... Ce qui signifie que vous auriez besoin un fichier de verrouillage à nouveau.

Pour référence, je ne pense pas qu'un fichier de verrouillage soit une mauvaise chose. C'est bien d'avoir une liste explicite de ce que vous devez construire. Et ça devrait le faire vite. Aucune logique magique n'est nécessaire.

@natefinch Si le fichier go.mod de l'application a été mis à jour pour exiger la v1.7.0 car l'outil de compatibilité externe a indiqué que la v1.6.0 était incompatible, vous n'auriez pas besoin d'un fichier de verrouillage. Étant donné que la spécification de la v1.7.0 se trouve dans le fichier go.mod, l'auteur peut également ajouter un commentaire expliquant pourquoi la v1.7.0 est utilisée et cette information serait utile aux lecteurs.

@leighmcculloch , si des fichiers de l'application sont mis à jour, il s'agit d'une version différente et totalement en dehors du problème de "construction reproductible sans fichier de verrouillage".

des informations sur la compatibilité hors bande sont proposées pour refléter l'évolution des connaissances : aucune incompatibilité n'était connue au moment de la publication, mais cela est ensuite devenu apparent et des informations supplémentaires sont publiées concernant les versions déjà publiées. À mon humble avis, par définition, cette approche entraîne un changement dans la manière dont les dépendances sont extraites, sinon pourquoi avoir ces informations d'incompatibilité d'extraction?

@redbaron @natefinch

L'intérêt des informations d'incompatibilité est que les auteurs de bibliothèques communiquent les informations d'incompatibilité à leurs utilisateurs. Que ces informations soient utilisées lors de la construction ou au moment de la publication est une question différente.

Dans le cas de vgo, l'idée actuelle est de n'afficher que les avertissements (ou potentiellement croasser). Mais surtout de ne pas le laisser influencer le choix des versions utilisées (car cela nécessiterait de résoudre SAT). Cela n'a donc pas d'importance, vous pouvez l'utiliser à l'un ou à l'autre et il remplira parfaitement son rôle, tout en conservant la propriété de répétabilité¹.

En détail, ces informations ne sont utilisées qu'au moment de la publication, puis enregistrées dans un fichier de verrouillage, qui est utilisé au moment de la construction. Il semble donc que nous envisagions une utilisation au moment de la publication "assez bonne" de toute façon, du moins en ce qui concerne les problèmes de vgo vs. dep.

Je ne pense toujours pas que nous devions répondre à ces questions pour le moment, cependant.


[1] Personnellement, je dirais qu'il est préférable de l'utiliser au moment de la publication et uniquement si -v est utilisé au moment de la construction, car un utilisateur ne devrait pas avoir à décider si un avertissement est actionnable ou non.

@rsc a écrit :

Pour continuer, une fois que nous avons établi les versions et vgo, nous voulons absolument avoir un nouveau godoc.org (peut-être un nom différent) qui enregistre des informations supplémentaires sur les packages, informations que la commande go peut consulter. Et certaines de ces informations seraient une incompatibilité par paires que la commande go pourrait signaler comme des avertissements ou des erreurs dans une version particulière (c'est-à-dire, signaler les dommages, ne pas essayer de les cacher en les contournant).

Je me demande s'il est nécessaire d'enregistrer l'incompatibilité par paire. La façon dont je le vois actuellement est que toute incompatibilité entre le module A@vN et le module B@vM est vraiment parce que B a fait un changement incompatible à partir d'une version vL où L < M.

Si le module B n'a pas fait de modification incompatible, alors le module A a juste un bogue. Si c'est le cas, alors le problème concerne B lui-même, pas l'appariement de A et B.

Ainsi ISTM que tout référentiel public de métadonnées de module ne peut enregistrer que les incompatibilités de tout module avec les versions précédentes de lui-même, ce qui peut rendre le problème plus facile à résoudre. Ces rapports d'incompatibilité sont assez similaires aux rapports de bogues, bien qu'ils ne puissent pas être résolus car une fois qu'une version est publiée, elle ne peut plus être modifiée.

Lorsque vous mettez à niveau vos versions de module, l'outil go peut prendre en compte les métadonnées et refuser de prendre en compte une version incompatible avec la version actuellement choisie. Je pense que cela évite d'avoir à résoudre SAT. Il pourrait également décider qu'un module donné a trop de rapports d'incompatibilité et refuser de l'ajouter en tant que dépendance.

Un ensemble de tuples de la forme ( module , oldVersion , newVersion , description ) peut être suffisant.

l'outil go pourrait considérer les métadonnées et refuser de considérer une version incompatible avec toute version actuellement choisie

Bien sûr, cela ne fonctionne pas lorsque vous ajoutez plusieurs dépendances, qui finissent par nécessiter l'utilisation de versions mutuellement incompatibles, car les nouvelles versions ne font pas partie du module existant, mais il peut y avoir une heuristique raisonnable disponible. Ce n'est pas crucial AFAICS, car les dépendances doivent être ajoutées relativement rarement.

Je crains que go release ne devienne le "compilateur suffisamment intelligent" de cette discussion. Que peuvent concrètement attendre les utilisateurs de go release dans Go 1.11/12 ? Je pense que cela fait une différence pour ce que sont les attentes raisonnables autour de MVS/SIV.

Merci pour l'énergie que vous avez si nombreux à apporter à Go et à cette proposition en particulier.

Le premier objectif du processus de proposition est de "[s]assurer que les propositions reçoivent une évaluation appropriée, juste, opportune et enregistrée avec une réponse claire". Cette proposition a été longuement discutée et nous avons publié un résumé de la discussion. Après six semaines et de nombreuses discussions, le comité d'examen de la proposition - intervenant en tant qu'arbitre parce que j'ai rédigé la proposition - a accepté la proposition.

Un seul problème GitHub est un endroit difficile pour avoir une discussion de grande envergure, car GitHub n'a pas de thread pour les différents volets de la conversation et n'affiche même plus tous les commentaires. La seule façon dont une discussion comme celle-ci fonctionne est de conserver activement le résumé de la discussion. Même le résumé était devenu compliqué au moment où la proposition a été acceptée.

Maintenant que la proposition est acceptée, cette question n'est plus le bon endroit pour discuter, et nous ne mettons plus à jour le résumé. Au lieu de cela, veuillez déposer de nouveaux problèmes ciblés sur les problèmes que vous rencontrez ou des suggestions concrètes de changements, afin que nous puissions avoir des discussions ciblées sur chaque sujet spécifique. Veuillez préfixer ces nouveaux problèmes avec « x/vgo : ». Si vous mentionnez # 24301 dans le texte du nouveau numéro, il sera alors renvoyé ici pour que d'autres puissent le trouver.

Un dernier point est qu'accepter la proposition signifie accepter l'idée, pas les bogues d'implémentation du prototype et tout. Il y a encore des détails à régler et des bugs à corriger, et nous continuerons à le faire ensemble.

Merci encore pour votre aide.

Il y a encore du travail à faire (voir l' étiquette des modules ) mais la mise en œuvre initiale du module telle que proposée dans ce numéro a été validée pour l'arborescence principale, je ferme donc ce numéro.

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