Go: cmd/go: agregar soporte de versión de paquete a la cadena de herramientas Go

Creado en 7 mar. 2018  ·  242Comentarios  ·  Fuente: golang/go

propuesta: agregar soporte de versión de paquete a la cadena de herramientas Go

Ya es hora de agregar versiones al vocabulario de trabajo tanto de los desarrolladores de Go como de nuestras herramientas.
La propuesta vinculada describe una forma de hacerlo. Ver especialmente la sección Justificación para una discusión de alternativas.

Este problema de GitHub es para debatir sobre el contenido de la propuesta.

Otras referencias:

Proposal Proposal-Accepted modules

Comentario más útil

Esta propuesta ha estado abierta con debates activos durante más de dos meses: @rsc y @spf13 realizaron sesiones de comentarios y recopilaron valiosos aportes de la comunidad que resultaron en revisiones de la propuesta. @rsc también ha realizado reuniones semanales con @sdboyer para obtener más comentarios. Se han proporcionado valiosos comentarios sobre la propuesta que han resultado en revisiones adicionales. Cada vez más, esta retroalimentación se refiere a la implementación que la acompaña en lugar de a la propuesta. Después de una revisión considerable, sentimos que es hora de aceptar esta propuesta y dejar que el amplio ecosistema de implementadores de herramientas de Go comience a realizar ajustes críticos para que nuestra base de usuarios pueda tener la mejor experiencia posible.

Ha habido dos objeciones a esta propuesta de las que creemos que deberíamos hablar:

  1. La propuesta requerirá que las personas cambien algunas de sus prácticas sobre el uso y la liberación de bibliotecas.
  2. La propuesta no logra dar una solución técnica a todos los posibles escenarios que puedan presentarse en relación con las incompatibilidades.

Estos son precisos en su observación pero funcionan según lo previsto. Los autores y usuarios de código _tendrán_ que cambiar algunas de sus prácticas sobre el uso y la liberación de bibliotecas, al igual que los desarrolladores se han adaptado a otros detalles de Go, como ejecutar gofmt. Cambiar las mejores prácticas es a veces la solución correcta. De manera similar, vgo no necesita manejar todas las situaciones posibles que involucran incompatibilidades. Como señaló Russ en su charla reciente en Gophercon Singapur , la única solución permanente a la incompatibilidad es trabajar juntos para corregir la incompatibilidad y mantener el ecosistema del paquete Go. Las soluciones temporales en una herramienta como vgo o dep solo necesitan funcionar el tiempo suficiente para que los desarrolladores tengan tiempo de resolver el problema real, y vgo hace este trabajo lo suficientemente bien.

Agradecemos todos los comentarios y la pasión que ha aportado a este problema crítico. La propuesta ha sido aceptada.

— El Comité de Revisión de Propuestas Go

Todos 242 comentarios

Preguntas frecuentes

Este comentario de problema responde a las preguntas más frecuentes, ya sea de la discusión a continuación o de otras discusiones. Otras preguntas de la discusión se encuentran en el comentario del próximo número.

¿Por qué la propuesta no es “usar Dep ”?

Al comienzo del viaje que condujo a esta propuesta, hace casi dos años, todos creíamos que la respuesta sería seguir el enfoque de versiones de paquetes ejemplificado por Ruby's Bundler y luego Rust's Cargo: versiones semánticas etiquetadas, un archivo de restricción de dependencia editado a mano. conocido como manifiesto, una descripción de dependencia transitiva separada generada por una máquina conocida como archivo de bloqueo, un solucionador de versiones para calcular un archivo de bloqueo que cumpla con el manifiesto y repositorios como la unidad de control de versiones. Dep sigue este plan aproximado casi exactamente y originalmente estaba destinado a servir como modelo para la integración del comando go. Sin embargo, cuanto más entendía los detalles del enfoque Bundler/Cargo/Dep y lo que significarían para Go, especialmente integrado en el comando go, y cuanto más discutía esos detalles con otros en el equipo Go, algunos de los detalles parecía cada vez menos adecuado para Go. La propuesta ajusta esos detalles con la esperanza de enviar un sistema que sea más fácil de entender y usar para los desarrolladores. Consulte la sección de justificación de la propuesta para obtener más información sobre los detalles específicos que queríamos cambiar, y también la publicación de blog que anuncia la propuesta .

¿Por qué deben aparecer los números de versión principales en las rutas de importación?

Para seguir la regla de compatibilidad de importación , que simplifica drásticamente el resto del sistema. Consulte también la publicación de blog que anuncia la propuesta , que habla más sobre la motivación y la justificación de la regla de compatibilidad de importación.

¿Por qué se omiten las versiones principales v0, v1 de las rutas de importación?

v1 se omite de las rutas de importación por dos razones. Primero, muchos desarrolladores crearán paquetes que nunca harán un cambio importante una vez que lleguen a la v1, que es algo que animamos desde el principio. No creemos que todos esos desarrolladores deban verse obligados a tener una versión 1 explícita cuando es posible que no tengan la intención de lanzar una versión 2. El v1 se convierte en solo ruido. Si esos desarrolladores finalmente crean una v2, la precisión adicional se activa entonces, para distinguirla de la predeterminada, v1. Hay buenos argumentos sobre la estabilidad visible para poner la v1 en todas partes, y si estuviéramos diseñando un sistema desde cero, tal vez sería una decisión difícil. Pero el peso del código existente inclina fuertemente la balanza a favor de omitir v1.

v0 se omite de las rutas de importación porque, según semver , no hay garantías de compatibilidad para esas versiones. Requerir un elemento v0 explícito haría poco para garantizar la compatibilidad; tendría que decir v0.1.2 para ser completamente preciso, actualizando todas las rutas de importación en cada actualización de la biblioteca. Eso parece una exageración. En cambio, esperamos que los desarrolladores simplemente miren la lista de módulos de los que dependen y desconfíen adecuadamente de cualquier versión v0.xy que encuentren.

Esto tiene el efecto de no distinguir v0 de v1 en las rutas de importación, pero normalmente v0 es una secuencia de cambios de interrupción que conducen a v1, por lo que tiene sentido tratar a v1 como el paso final en esa secuencia de interrupción, no como algo que deba distinguirse de v0. . Como dijo @Merovius (https://github.com/golang/go/issues/24301#issuecomment-376213693):

Al usar v0.x, acepta que v0.(x+1) podría obligarlo a corregir su código. ¿Por qué es un problema si v0.(x+1) se llama v1.0 en su lugar?

Finalmente, la omisión de las versiones principales v0 y v1 es obligatoria, no opcional, para que haya una única ruta de importación canónica para cada paquete.

¿Por qué debo crear una nueva rama para v2 en lugar de continuar trabajando en el maestro?

No tienes que crear una nueva rama. Desafortunadamente, la publicación de módulos vgo da esa impresión en su discusión sobre el diseño del repositorio de "rama principal". Pero a vgo no le importan las ramas. Solo busca etiquetas y resuelve a qué confirmaciones específicas apuntan. Si desarrolla v1 en maestro, decide que ha terminado por completo con v1 y desea comenzar a realizar confirmaciones de v2 en maestro, está bien: comience a etiquetar maestro con etiquetas v2.xy. Pero tenga en cuenta que algunos de sus usuarios seguirán usando v1, y es posible que ocasionalmente desee realizar una corrección de errores menores de v1. Es posible que al menos desee bifurcar una nueva rama v1 para ese trabajo en el punto en el que comienza a usar master para v2.

¿La selección mínima de versiones no evitará que los desarrolladores obtengan actualizaciones importantes?

Este es un miedo común, pero realmente creo que, en todo caso, sucederá lo contrario. Citando la sección "Velocidad de actualización" de https://research.swtch.com/vgo-mvs :

Dado que la selección de versión mínima toma la versión mínima permitida de cada dependencia, es fácil pensar que esto conduciría al uso de copias muy antiguas de los paquetes, lo que a su vez podría generar errores innecesarios o problemas de seguridad. En la práctica, sin embargo, creo que sucederá lo contrario, porque la versión mínima permitida es la máxima de todas las restricciones, por lo que la única palanca de control disponible para todos los módulos en una compilación es la capacidad de forzar el uso de una versión más nueva. de una dependencia que de otro modo se usaría. Espero que los usuarios con una selección mínima de versiones terminen con programas casi tan actualizados como sus amigos que usan sistemas más agresivos como Cargo.

Por ejemplo, suponga que está escribiendo un programa que depende de un puñado de otros módulos, todos los cuales dependen de algún módulo muy común, como gopkg.in/yaml.v2. La compilación de su programa utilizará la versión YAML más reciente entre las solicitadas por su módulo y ese puñado de dependencias. Incluso una sola dependencia consciente puede obligar a su compilación a actualizar muchas otras dependencias. Esto es lo opuesto al problema del cliente de Kubernetes Go que mencioné anteriormente.

En todo caso, la selección de la versión mínima sufriría el problema opuesto, que esta respuesta de "máximo de los mínimos" sirve como un trinquete que hace que las dependencias avancen demasiado rápido. Pero creo que, en la práctica, las dependencias avanzarán a la velocidad correcta, lo que termina siendo la cantidad justa más lenta que Cargo y sus amigos.

Por "cantidad correcta más lenta" me refería a la propiedad clave de que las actualizaciones ocurren solo cuando las solicita, no cuando no las ha hecho. Eso significa que el código solo cambia (de formas potencialmente inesperadas y novedosas) cuando espera que suceda y está listo para probarlo, depurarlo, etc.

Consulte también la respuesta https://github.com/golang/go/issues/24301#issuecomment -375992900 de @Merovius.

Si $GOPATH está en desuso, ¿dónde vive el código descargado?

El código que verifica, trabaja y modifica se puede almacenar en cualquier lugar de su sistema de archivos, al igual que con cualquier otra herramienta de desarrollo.

Vgo necesita algo de espacio para guardar el código fuente descargado e instalar archivos binarios, y para eso todavía usa $GOPATH, que a partir de Go 1.9 tiene como valor predeterminado $HOME/go. Por lo tanto, los desarrolladores nunca necesitarán establecer $GOPATH a menos que deseen que estos archivos estén en un directorio diferente. Para cambiar solo la ubicación de instalación binaria, pueden configurar $GOBIN (como siempre).

¿Por qué estás introduciendo el comentario // import ?

No eran. Esa era una convención preexistente . El punto de ese ejemplo en el recorrido fue mostrar cómo go.mod puede deducir las rutas de módulo correctas de los comentarios de importación, si existen. Una vez que todos los proyectos usen archivos go.mod , los comentarios de importación serán completamente redundantes y probablemente obsoletos.

Resumen de la discusión (última actualización 2017-04-25)

Este comentario de problema contiene un resumen de la discusión a continuación.

¿Cómo podemos manejar la migración?

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

Respuesta https://github.com/golang/go/issues/24301#issuecomment -377529520 por @rsc. La propuesta original asume que la migración está a cargo de los autores que se trasladan a los subdirectorios cuando la compatibilidad es importante para ellos, pero, por supuesto, esa motivación es incorrecta. La compatibilidad es más importante para los usuarios, que tienen poca influencia en el movimiento de los autores. Y no ayuda a las versiones anteriores. El comentario vinculado, ahora también #25069, propone un cambio mínimo al antiguo "ir a compilar" para poder consumir y compilar código compatible con módulos.

¿Cómo podemos lidiar con los registros singleton?

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

Respuesta https://github.com/golang/go/issues/24301#issuecomment -377527249 por @rsc. Las colisiones de registro de Singleton (como http.Handle de la misma ruta) entre módulos completamente diferentes no se ven afectadas por la propuesta. Para las colisiones entre diferentes versiones principales de un solo módulo, los autores pueden escribir las diferentes versiones principales para esperar que se coordinen, generalmente haciendo que v1 llame a v2, y luego usen un ciclo de requisitos para asegurarse de que v2 no se use con v1 anterior que no No sé sobre la coordinación.

¿Cómo debemos instalar un comando versionado?

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

Respuesta https://github.com/golang/go/issues/24301#issuecomment -377417565 por @rsc. En resumen, usa go get. Todavía usamos $GOPATH/bin para la ubicación de instalación. Recuerde que $GOPATH ahora tiene como valor predeterminado $HOME/go, por lo que los comandos terminarán en $HOME/go/bin, y $GOBIN puede anular eso.

¿Por qué se omiten v0, v1 en las rutas de importación? ¿Por qué deben aparecer los demás? ¿Por qué nunca deben aparecer v0, v1?

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

Agregado a las preguntas frecuentes anteriores.

¿Por qué se mencionan los archivos zip en la propuesta?

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

El ecosistema se beneficiará de definir un formato de intercambio concreto. Eso habilitará proxies y otras herramientas. Al mismo tiempo, estamos abandonando el uso directo del control de versiones (consulte la justificación en la parte superior de esta publicación ). Ambos motivan la descripción del formato específico. La mayoría de los desarrolladores no necesitarán pensar en archivos zip en absoluto; ningún desarrollador necesitará mirar dentro de ellos, a menos que estén creando algo como godoc.org.

Ver también #24057 sobre zip vs tar.

¿Poner versiones principales en las rutas de importación no infringe DRY?

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

No, porque la semántica de una importación debería ser comprensible sin hacer referencia al archivo go.mod. El archivo go.mod solo especifica detalles más finos. Consulte la segunda mitad de la sección de versiones de importación semántica de la propuesta , comenzando en la cita en bloque.

Además, si SECA demasiado, termina con sistemas frágiles. La redundancia puede ser algo bueno. Entonces, "violar [ing] DRY", es decir, limitarse a repetirse a sí mismo, no siempre es malo. Por ejemplo, colocamos la cláusula del paquete en cada archivo .go del directorio, no solo en uno. Eso detectó errores honestos desde el principio y luego se convirtió en una manera fácil de distinguir paquetes de prueba externos (paquete x vs paquete x_test). Hay un equilibrio que alcanzar.

¿Qué zona horaria se usa para la marca de tiempo en las pseudoversiones?

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

UTC. Tenga en cuenta también que nunca tendrá que escribir una pseudo-versión usted mismo. Puede escribir un hash de confirmación de git (o un prefijo de hash) y vgo calculará y sustituirá la pseudoversión adecuada.

¿Vgo abordará dependencias que no sean de Go, como C o búferes de protocolo? ¿Código generado?

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

El desarrollo Non-Go sigue sin ser un objetivo del comando go , por lo que no habrá soporte para administrar bibliotecas C y demás, ni habrá soporte explícito para búferes de protocolo.

Dicho esto, ciertamente entendemos que el uso de búferes de protocolo con Go es demasiado difícil, y nos gustaría ver que se aborde por separado.

En cuanto al código generado de manera más general, la respuesta es un verdadero sistema de compilación multilingüe, específicamente porque no queremos que todos los usuarios necesiten tener instalados los generadores correctos. Es mejor que el autor ejecute los generadores y verifique el resultado.

¿La selección mínima de versiones no evitará que los desarrolladores obtengan actualizaciones importantes?

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

Añadido a preguntas frecuentes.

### ¿Puedo usar master para desarrollar v1 y luego reutilizarlo para desarrollar v2?

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

Si. Añadido a preguntas frecuentes.

¿Cuál es la línea de tiempo para esto?

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

Respuesta en https://github.com/golang/go/issues/24301#issuecomment -377413777 por @rsc. En resumen, el objetivo es obtener una "vista previa de tecnología" en Go 1.11; el trabajo puede continuar unas pocas semanas después de la congelación, pero no más. Probablemente no envíe PR agregando go.mod a cada biblioteca que pueda encontrar hasta que la propuesta se marque como aceptada y la copia de desarrollo de cmd/go se haya actualizado.

¿Cómo puedo hacer un cambio de seguridad incompatible con versiones anteriores?

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

Respuesta en https://github.com/golang/go/issues/24301#issuecomment -377415652 por @rsc. En resumen, las pautas de compatibilidad de Go 1 permiten realizar cambios importantes por razones de seguridad para evitar modificar la versión principal, pero siempre es mejor hacerlo de manera que el código existente siga funcionando tanto como sea posible. Por ejemplo, no elimine una función. En su lugar, haga que la función entre en pánico o registre. Solo es fatal si se llama incorrectamente.

Si un repositorio contiene diferentes módulos en subdirectorios (digamos, v2, v3, v4), ¿vgo puede mezclar y combinar diferentes confirmaciones?

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

Si. Trata cada etiqueta de versión como correspondiente solo a un subárbol del repositorio general y puede usar una etiqueta diferente (y, por lo tanto, una confirmación diferente) para cada decisión.

¿Qué pasa si los proyectos hacen un mal uso del semver? ¿Deberíamos permitir versiones secundarias en las rutas de importación?

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

Como señala @powerman , definitivamente debemos proporcionar un verificador de consistencia de API para que los proyectos al menos puedan saber cuándo están a punto de lanzar un cambio obviamente importante.

¿Puede determinar si tiene más de un paquete en una compilación?

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

Lo más fácil sería usar goversion -m en el binario resultante. Deberíamos hacer una opción de ir para mostrar lo mismo sin construir el binario.

Inquietudes sobre la dependencia de vgo en el proxy frente al proveedor, especialmente el código abierto frente a la empresa.

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

Respuesta: [ https://github.com/golang/go/issues/24301#issuecomment -377411175 by @rsc.] Tanto el proxy como el proveedor serán compatibles. El proxy es muy importante para la empresa y el proveedor es muy importante para el código abierto. También queremos construir una red espejo confiable, pero solo una vez que vgo se convierta en go.

Preocupaciones sobre protobuild dependiendo de la semántica de GOPATH.

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

La respuesta [ https://github.com/golang/go/issues/24301#issuecomment -377602765 by @rsc] solicitó más detalles en un nuevo problema, pero ese problema no parece haberse archivado.

Sugerencia para agregar una etiqueta especial vgo-v1-lock .

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

Parece atractivo al principio, pero conduce a casos especiales que probablemente no valga la pena asumir. Respuesta completa en https://github.com/golang/go/issues/24301#issuecomment -384344659.

¿Cómo se parchea una dependencia profunda sin vender?

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

Respuesta [ https://github.com/golang/go/issues/24301#issuecomment -378261916 by @kardianos.] Mediante el uso de una directiva de reemplazo.

¿Qué haremos con el cambio de nombre de los módulos?

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

Respuesta [ https://github.com/golang/go/issues/24301#issuecomment -379307176 por @rsc.]
Estos son problemas reales y preexistentes que la propuesta de vgo no intenta abordar directamente, pero claramente deberíamos abordarlos eventualmente. La respuesta a la desaparición del código es tener proxies de almacenamiento en caché (espejos) junto con una razón para confiar en ellos; eso es trabajo futuro. (O use la venta en un proyecto de nivel superior si lo prefiere). La respuesta al movimiento de código es agregar un concepto explícito de redirecciones de módulos o paquetes, al igual que los alias de tipo son redirecciones de tipo; eso también es trabajo futuro.

¿Qué pasa con la conexión a los servidores Git locales?

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

El acceso directo de git se ha vuelto a agregar al plan. Ver #24915.

¿Qué pasa con los paquetes solo binarios?

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

Los paquetes solo binarios solo han sido compatibles en la circunstancia limitada de algún tipo de instalación fuera de banda en GOPATH/pkg. Go get nunca admitió la obtención e instalación de un paquete solo binario, y seguirá sin admitirlo. Un paquete solo binario solo funciona con un compilador particular y una copia particular de las dependencias, lo que limita severamente qué tan bien se puede admitir. La respuesta correcta es casi siempre usar el código fuente en su lugar.

¿Deberíamos usar la sintaxis ruta@versión en el archivo go.mod?

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

Este es el #24119. Parecía una buena idea al principio pero, después de una cuidadosa consideración, no.

.

.

Cambio https://golang.org/cl/101678 menciona este problema: design: add 24301-versioned-go

Esta propuesta es impresionante y me gusta casi todo sobre ella. Sin embargo, publiqué la siguiente inquietud en la lista de correo, pero nunca recibí ninguna respuesta. Mientras tanto, he visto este problema planteado por otros en el canal de holgura de Gophers para vgo y tampoco he visto una respuesta satisfactoria allí.

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

Lo que más me preocupa es que la ruta de migración entre un mundo anterior a vgo y un mundo vgo vaya mal. Creo que corremos el riesgo de infligir un gran dolor a la comunidad de Go si no hay una ruta de migración sin problemas. Claramente, la migración no puede ser atómica en toda la comunidad, pero si he entendido todo lo que ha escrito sobre vgo hasta ahora, puede haber algunas situaciones en las que los paquetes existentes ampliamente utilizados no se puedan utilizar tanto con las herramientas previas a vgo como con las posteriores. -herramientas vgo.

Específicamente, creo que los paquetes existentes que ya tienen lanzamientos etiquetados con versiones principales >= 2 no funcionarán con vgo hasta que tengan un archivo go.mod y también se importen con una ruta de importación aumentada /vN. Sin embargo, una vez que se realicen esos cambios en el repositorio, se interrumpirán los usos del paquete anteriores a vgo.

Esto parece crear un tipo diferente de problema de importación de diamantes en el que los dos paquetes hermanos en el medio del diamante importan un paquete v2+ común. Me preocupa que los paquetes hermanos deban adoptar rutas de importación vgo atómicamente para evitar que el paquete en la parte superior del diamante se encuentre en un estado imposible de compilar, ya sea que use herramientas vgo o pre-vgo.

Todavía no he visto nada que explique la ruta de migración en este escenario.

La propuesta dice:

Las compilaciones compatibles con módulos pueden importar paquetes no compatibles con módulos (aquellos fuera de un árbol con un archivo go.mod) siempre que estén etiquetados con una versión semántica v0 o v1. También pueden hacer referencia a cualquier confirmación específica mediante una "pseudoversión" del formulario v0.0.0-yyyymmddhhmmss-commit. El formulario de pseudoversión permite hacer referencia a confirmaciones sin etiquetar, así como confirmaciones que están etiquetadas con versiones semánticas en v2 o superior, pero que no siguen la convención de control de versiones de importación semántica.

Pero no veo una forma de que los paquetes que no son compatibles con módulos importen paquetes compatibles con módulos con dependencias transitivas >= v2. Eso parece causar la fragmentación del ecosistema de una manera que aún no se ha abordado. Una vez que tiene una dependencia compatible con módulos que tiene un paquete >= v2 en algún lugar de sus dependencias transitivas, parece obligar a todos sus dependientes a adoptar también vgo para mantener la compilación en funcionamiento.

Actualización: consulte también https://github.com/golang/go/issues/24454

El proyecto Go ha alentado esta convención desde el comienzo del proyecto, pero esta propuesta le da más fuerza: las actualizaciones de los usuarios del paquete tendrán éxito o fallarán solo en la medida en que los autores del paquete sigan la regla de compatibilidad de importación.

No me queda claro qué significa esto y cómo cambia la situación actual. Me parece que esto también describe la situación actual: si rompo esta regla, las actualizaciones y el go-get fallarán. AIUI nada cambia realmente y sugeriría eliminar al menos la mención de "más dientes". A menos, por supuesto, que este párrafo insinúe que existen mecanismos adicionales para penalizar/prevenir roturas.

Esto también afectaría cosas como los controladores de base de datos y los formatos de imagen que se registran con otro paquete durante el inicio, ya que múltiples versiones principales del mismo paquete pueden terminar haciendo esto. No me queda claro cuáles serían todas las repercusiones de eso.

Si la versión principal es v0 o v1, entonces se debe omitir el elemento del número de versión; de lo contrario, debe incluirse.

¿Por qué es esto? En la publicación vinculada, solo veo la razón de que esto es lo que los desarrolladores hacen actualmente para crear rutas alternativas cuando realizan cambios importantes, pero esta es una solución por el hecho de que inicialmente no planean las herramientas que no manejan las versiones para ellos. . Si estamos cambiando a una nueva práctica, ¿por qué no permitir y alentar (o incluso exigir) que los nuevos paquetes habilitados para vgo incluyan v0 o v1 ? Parece que los caminos que carecen de versiones son solo oportunidades para la confusión. (¿Es este un paquete de estilo vgo? ¿Dónde está el límite del módulo? etc.)

En general, me gusta la propuesta, pero estoy obsesionado con exigir versiones principales en las rutas de importación:

  1. Viola el principio DRY cuando la versión principal ya se puede conocer a partir de go.mod . Comprender lo que sucederá si hay una falta de coincidencia entre los dos también es difícil de intuir.
  2. La irregularidad de permitir que v0 y v1 estén ausentes tampoco es intuitiva.
  3. Cambiar todas las rutas de importación al actualizar una dependencia parece potencialmente tedioso.

Entiendo que los escenarios como el ejemplo de moauth deben ser factibles, pero espero que no a expensas de simplificar las cosas para los escenarios más comunes.

En primer lugar: ¡Impresionante trabajo!

Una cosa que no está del todo clara para mí y parece un poco subespecificada:

¿Por qué hay archivos zip en esta propuesta?

El diseño, las restricciones y los múltiples casos de uso, como cuándo se crea y cómo se gestiona su ciclo de vida, qué herramientas necesitan soporte, cómo deben interactuar herramientas como linters tampoco están claros, porque no están cubiertos en la propuesta.

Por lo tanto, sugeriría referirse a una propuesta posterior, aún no escrita, aquí y eliminar la palabra zip o eliminar la parte completa del texto de la propuesta, si planea no discutirla en absoluto dentro del alcance de esta propuesta.

Discutir esto más adelante también permite que diferentes audiencias contribuyan mejor aquí.

¿Qué zona horaria se usa para la marca de tiempo en la pseudoversión (v0.0.0-yyyymmddhhmmss-commit)?

Editar:
Está en UTC como se indica en https://research.swtch.com/vgo-module.

@rsc ¿Abordará las dependencias de C?

Parece que la selección de versión mínima hace que la propagación de cambios no disruptivos sea muy lenta. Supongamos que tenemos una biblioteca popular, Foo, que utilizan los proyectos A, B y C. Alguien mejora el rendimiento de Foo sin cambiar la API. Actualmente recibir actualizaciones es un proceso de exclusión voluntaria. Si el proyecto A vendió Foo, pero B y C no lo hicieron, el autor solo necesita enviar pr con la actualización de la dependencia del proveedor a A. Por lo tanto, las contribuciones que no rompen la API no tendrán tanto efecto en la comunidad y se desaconsejan un poco en comparación con las actuales. situación. Esto es aún más problemático para las actualizaciones de seguridad. Si algún proyecto abandonado/pequeño/no muy activo (no una biblioteca) declara una dependencia directa de la versión anterior de, por ejemplo, x/crypto, todos los usuarios de ese proyecto serán vulnerables a fallas en x/crypto hasta que el proyecto se actualice, potencialmente para siempre. Actualmente, los usuarios de dichos proyectos recibirán la última versión corregida, por lo que esto empeora la situación de seguridad. IIRC hubo algunas sugerencias sobre cómo solucionar esto en la discusión de la lista de correo, pero, por lo que sé, esta propuesta no lo menciona.

IIRC hubo algunas sugerencias sobre cómo arreglar [obtener parches de seguridad] en la discusión de la lista de correo, pero, por lo que sé, esta propuesta no lo menciona.

Ver la mención de go get -p .

Ver la mención de ir a buscar -p.

Lo he visto, pero sigue siendo un mecanismo de suscripción.
Estaba pensando en la forma en que la biblioteca marcaría todas las versiones anteriores como inseguras, para obligar al usuario a ejecutar go get -p o explícitamente optar por una biblioteca insegura.

Si el soporte para go get , tal como lo conocemos hoy, quedará obsoleto y finalmente se eliminará, ¿cuál es la forma recomendada de obtener e instalar (sin etiquetar) los archivos binarios de Go? ¿Requiere git clone hacer el proyecto primero, seguido de un manual go install para instalar el binario?
Si $GOPATH está en desuso, ¿dónde se instalarán estos archivos binarios?

@leonklingele : según tengo entendido, go get no quedará en desuso, al contrario.
Se mejorará con capacidades de control de versiones automáticas y transparentes. Si un proyecto depende de un proyecto sin etiquetar, simplemente tomaría el maestro y lo "vendería" en esta versión exacta.
Nuevamente, mi propio entendimiento al leer un poco sobre vgo. Todavía estoy en el proceso de entenderlo completamente.

Me pregunto cómo afectará esto al flujo de trabajo con un repositorio de Git en general, y también me baso en esta oración de la propuesta:

Si la versión principal es v0 o v1, entonces se debe omitir el elemento del número de versión; de lo contrario, debe incluirse.

Por el momento, parece común trabajar en el maestro (para mí, esto incluye ramas de funciones de corta duración) y etiquetar una confirmación con una nueva versión de vez en cuando. Siento que este flujo de trabajo se vuelve más confuso con los módulos Go tan pronto como lanzo la v2 de mi biblioteca, porque ahora tengo una rama master y una rama v2 . Esperaría que master fuera la rama actual y v2 una rama de mantenimiento, pero es exactamente al revés.

Sé que la rama predeterminada se puede cambiar de master a v2 , pero esto aún me deja con la tarea de actualizar eso cada vez que lanzo una nueva versión principal. Personalmente, preferiría tener una sucursal master y una v1 , pero no estoy seguro de cómo se ajustaría exactamente a la propuesta.

Los nuevos lanzamientos importantes causan abandono. Si tiene que cambiar una configuración en su repositorio de Git (la rama predeterminada) cada vez que realiza una nueva versión, ese es un costo muy pequeño en comparación con los usuarios de su biblioteca que cambian a la nueva versión.

Creo que este aspecto de la propuesta establece el incentivo correcto: alienta a los autores anteriores a pensar en cómo pueden hacer cambios de una manera compatible con versiones anteriores, reduciendo la rotación general del ecosistema.

ahora tengo un maestro y una rama v2

En su lugar, puede crear un subdirectorio v2/ en master.

@mrkanister

Preferiría tener un maestro y una rama v1, pero no estoy seguro de cómo se ajustaría exactamente a la propuesta.

Según mi comprensión de https://research.swtch.com/vgo-module , vgo usa etiquetas, no ramas, para identificar las versiones. Por lo tanto, puede mantener el desarrollo en el maestro y ramificarse v1 siempre que las etiquetas apunten a la ramificación y confirmación correctas.

Los nuevos lanzamientos importantes causan abandono. Si tiene que cambiar una configuración en su repositorio de Git (la rama predeterminada) cada vez que realiza una nueva versión, ese es un costo muy pequeño en comparación con los usuarios de su biblioteca que cambian a la nueva versión.

Este es un estilo de pensamiento problemático que creo que ha mordido a Go duro en el pasado. Para una persona en un proyecto, cambiar la rama predeterminada es simple en este momento, sí. Pero ir en contra de las convenciones del flujo de trabajo hará que la gente se olvide, especialmente cuando trabajan en varios idiomas. Y será un ejemplo más peculiar de cómo Go hace las cosas de manera totalmente diferente que los recién llegados tienen que aprender. Ir en contra de las convenciones comunes del flujo de trabajo de los programadores _no es en absoluto_ un costo menor.

Ir en contra de las convenciones comunes del flujo de trabajo de los programadores no es un costo menor.

No seguir el camino convencional es a veces la condición necesaria para la innovación.

Si entendí partes de la propuesta correctamente, nunca tienes que crear un subdirectorio o una nueva rama. Potencialmente, solo puede tener una rama maestra y etiquetar git su repositorio de 0.0, a 1.0, a 2.0 y así sucesivamente , siempre y cuando se asegure de actualizar su go.module a la ruta de importación correcta para su biblioteca.

@mrkanister Creo que, para desarrolladores, clona tu maestro (o cualquier rama de desarrollo) y usa la directiva "reemplazar" (ver vgo-tour) para señalarlo. (si entiendo lo que quieres decir, no estoy seguro).

@rsc Me gustaría pedirle que sea más preciso sobre la hoja de ruta y lo que debemos hacer ahora.
¿Seguirá la política de Go y la característica de congelación de vgo a los 3 meses (2 ahora)?
¿Deberíamos ir ahora con nuestro bastón de peregrino pidiendo a todos los mantenedores de libs que agreguen un archivo go.mod o deberíamos esperar a que la propuesta sea aceptada oficialmente (para asegurarnos de que el nombre y la sintaxis no cambien)?

Las herramientas de @flibustenet no están cubiertas por la política 1.0, por lo que cualquier cosa puede cambiar.

https://golang.org/doc/go1compat

Finalmente, la cadena de herramientas de Go (compiladores, enlazadores, herramientas de construcción, etc.) está en desarrollo activo y puede cambiar el comportamiento. Esto significa, por ejemplo, que las secuencias de comandos que dependen de la ubicación y las propiedades de las herramientas pueden romperse con una versión puntual.

También de la propuesta

El plan, sujeto a la aprobación de la propuesta, es lanzar el soporte del módulo en Go 1.11 como una característica opcional que aún puede cambiar. El lanzamiento de Go 1.11 brindará a los usuarios la oportunidad de usar módulos "de verdad" y brindar comentarios críticos. Aunque los detalles pueden cambiar, las versiones futuras podrán consumir árboles fuente compatibles con Go 1.11. Por ejemplo, Go 1.12 comprenderá cómo consumir la sintaxis del archivo go.mod de Go 1.11, incluso si para entonces la sintaxis del archivo o incluso el nombre del archivo ha cambiado. En una versión posterior (digamos, Go 1.12), declararemos que el soporte del módulo se ha completado. En una versión posterior (por ejemplo, Go 1.13), finalizaremos la compatibilidad con go get de los que no son módulos. El apoyo para trabajar en GOPATH continuará indefinidamente.

Gracias por la respuesta.

@AlexRouSg

Según mi comprensión de https://research.swtch.com/vgo-module , vgo usa etiquetas, no ramas, para identificar las versiones. Por lo tanto, puede mantener el desarrollo en el maestro y ramificarse v1 siempre que las etiquetas apunten a la ramificación y confirmación correctas.

Tiene razón, esto seguirá funcionando como antes (solo verifique dos veces para estar seguro), ¡buena captura!

Con eso fuera del camino, lo que yo (y aparentemente otros) no entiendo es el razonamiento detrás de no permitir que exista un paquete v1 . Traté de importar uno usando /v1 al final de la importación y también lo agregué a los go.mod del paquete que se está importando, pero vgo buscará una carpeta llamada v1 en su lugar.

@mrkanister
Creo que la razón principal para no permitir v1 o v0 en la ruta de importación es garantizar que solo haya una ruta de importación para cada versión compatible de un paquete.
El uso de la ruta de importación simple en lugar de /v1 es para facilitar la transición, por lo que no tiene que actualizar todas sus rutas de importación para agregar /v1 al final.

Hola,

Si bien muchos de los puntos de la propuesta son más que bienvenidos y ayudarán a controlar las grandes bases de código de Go que surgieron con el tiempo, la regla de "usar la versión mínima" es bastante dañina:

  • desea que su ecosistema de código progrese. Eso significa que desea que las personas prueben y usen nuevas versiones y detecten los problemas antes de que se acumulen.
  • desea que los nuevos lanzamientos de módulos, que corrigen problemas de seguridad, se apliquen lo antes posible
  • desea poder aplicar nuevas versiones de módulos, que solucionen problemas de seguridad, tan pronto como sea posible. No siempre están etiquetados en arreglos de seguridad. Si evita nuevos lanzamientos, también evita esas correcciones
  • Incluso cuando una nueva versión no contiene correcciones de seguridad, la aplicación temprana de los cambios significa que habrá menos cambios para examinar cuando se publique la próxima versión que sí contenga correcciones de seguridad (y lo último que desea cuando se publica dicha versión y necesita ser rápido es atascarse en cambios intermedios que no había visto antes).
  • aplicar versiones intermedias solo es dañino si rompen la compatibilidad, y no deberían romper la compatibilidad, y si rompen la compatibilidad, es mejor detectarlo e informar a los autores del módulo antes de que lo conviertan en un hábito para las próximas versiones, eventualmente lo hará absolutamente necesitar.
  • no desea que los fragmentos de código antiguos lo arrastren hacia abajo porque aún especifican una versión de dependencia antigua y nadie encuentra el tiempo para actualizar su manifiesto. El uso de la última versión de un lanzamiento importante satisface esta necesidad social en otros ecosistemas de código: obligar a los desarrolladores a probar la última versión y no posponer hasta que sea demasiado tarde porque "hay cosas más importantes" (es decir, más divertidas) que hacer.

    • mientras que, en teoría, puede enviar un número ilimitado de versiones de módulos para que cada pieza de código pueda usar la que desee, en la práctica, tan pronto como componga dos módulos que usen la misma dependencia, debe elegir una versión, por lo que cuanto más complejo sea su es el software, menos tolerará múltiples versiones. Así que pronto te encuentras con el viejo problema de qué hacer con los rezagados que ralentizan todo el convoy. Nunca conocí una cultura humana que manejara este problema diciéndole a los rezagados "tienes razón, ve tan lento como quieras, todos te esperarán". Puede ser agradable y altruista, pero no es productivo.

Combatir la inercia humana es duro y doloroso, y lo hacemos porque es necesario para progresar, no porque sea agradable. Hacer herramientas agradables que eviten el problema e inciten a los humanos a procrastinar un poco más no ayuda en absoluto, solo acelerará la sedimentación del proyecto y la acumulación de deuda técnica. Ya hay docenas de proyectos de Go en github con la mayor parte de su archivo Léame dedicado al autor rogando a sus usuarios que actualicen porque hizo correcciones importantes, el problema se generalizará al usar la versión más antigua de forma predeterminada.

Una buena regla sería "usar la última versión que coincida con la versión principal, no todas las confirmaciones intermedias". Eso sería un compromiso en el futuro y la estabilidad. Pone al proyecto original al mando, que conoce mejor la base de código y puede decidir con cordura cuándo cambiar a sus usuarios a un nuevo estado de código.

Mi pregunta sin respuesta copiada de la lista de correo:

Esperamos que la mayoría de los desarrolladores prefieran seguir la convención habitual de "rama principal", en la que las diferentes versiones principales viven en diferentes ramas. En este caso, el directorio raíz en una rama v2 tendría go.mod indicando v2, así:

Parece que hay subdirectorios y esta importante convención de ramas que son compatibles con vgo. En mi experiencia anecdótica, ningún repositorio sigue esta convención en Go u otros idiomas (en realidad, no puedo pensar en uno solo que no sean los obligados por gopkg.in, que parece relativamente poco utilizado en estos días). La rama maestra es lo más reciente y tiene etiquetas v2.3.4 en su historial. Las etiquetas existen para separar todo (no solo las versiones menores). Si es necesario parchear una versión anterior, se crea temporalmente una rama a partir de la última etiqueta v1, se envían confirmaciones, se envía una nueva etiqueta y la rama se elimina sumariamente. No hay una rama para las versiones, son solo ramas maestras/de desarrollo/características actuales + etiquetas de versión. Sé que "todo es una referencia" en Git, pero para otros VCS, la distinción puede no ser tan confusa.

Habiendo dicho eso, probé el flujo de trabajo descrito anteriormente con vgo (solo con etiquetas que dicen v2.0.0, v2.0.1 y sin ramas) y parece funcionar. Así que mi pregunta es: aunque esto funciona ahora, ¿es intencionado? Como no parece tan completamente descrito como los otros dos flujos de trabajo en el blog, y quiero asegurarme de que trabajar sin una rama v2/v3... no es una funcionalidad accidental que desaparecerá ya que, como expliqué anteriormente, nunca he visto este (u otro) flujo de trabajo descrito en la publicación para ser adoptado masivamente por cualquier persona (especialmente fuera de la comunidad Go).

Por supuesto, mi argumento se reduce a preferencias y anécdotas, por lo que estaría dispuesto a hacer un repo-scraping para probar esto en todos los idiomas si es necesario. Hasta ahora, me han gustado mucho las publicaciones de propuestas y, en general, estoy de acuerdo con los cambios, continuaré siguiéndolos y jugando con vgo.

Gracias por todos sus esfuerzos.

¿Alguien puede aclarar cómo funcionaría el modelo alternativo propuesto para MVS para mejorar la cadencia de actualización? Porque no me queda claro. Mi comprensión del modelo alternativo (ampliamente utilizado) es

  • El desarrollador crea un manifiesto hecho a mano, enumerando las restricciones de versión para todas las dependencias utilizadas
  • El desarrollador ejecuta $solver, que crea un archivo de bloqueo, enumerando un subconjunto elegido de versiones de dependencia transitiva que satisfacen las restricciones especificadas
  • Este archivo de bloqueo se confirma y se usa en el momento de la compilación y la instalación para garantizar compilaciones reproducibles.
  • Cuando se lanza una nueva versión de una dependencia y se va a usar, el desarrollador potencialmente actualiza el manifiesto, vuelve a ejecutar el solucionador y vuelve a confirmar el nuevo archivo de bloqueo.

El modelo MVS propuesto tal como lo entiendo es

  • El desarrollador genera automáticamente go.mod , en función del conjunto de rutas de importación en el módulo, seleccionando la versión actual más reciente de cualquier dependencia transitiva
  • go.mod se compromete y se usa para obtener límites inferiores en las versiones en el momento de la compilación y la instalación. MVS garantiza compilaciones reproducibles
  • Cuando se lanza una nueva versión de una dependencia y se va a utilizar, el desarrollador ejecuta vgo get -u , que obtiene las versiones más recientes de las dependencias transitivas y sobrescribe go.mod con los nuevos límites inferiores. Eso luego se envía.

Parece que debo pasar por alto algo y sería útil si alguien señalara qué. Debido a que este entendimiento parece implicar que debido a los archivos de bloqueo que especifican las versiones exactas y las que se usan en la compilación real, MVS es mejor para aumentar la cadencia de actualización, ya que no permite retrasar las versiones, en general.

Claramente me estoy perdiendo algo (y me sentiré estúpido en unos 5 m), ¿qué es eso?

@tpng

El uso de la ruta de importación simple en lugar de /v1 es para facilitar la transición, por lo que no tiene que actualizar todas sus rutas de importación para agregar /v1 al final.

Esto en realidad no debería ser necesario. Déjame dar un ejemplo:

Un usuario está usando actualmente, por ejemplo v1.0.0 de una biblioteca, fijada por un administrador de dependencias y la etiqueta en el repositorio ascendente. Ahora upstream decide crear un go.mod y también llama al módulo /v1 . Esto debería resultar en una nueva confirmación y una nueva etiqueta (por ejemplo v1.0.1 ). Dado que vgo nunca intentará actualizar las dependencias por sí solo, esto no debería romper nada para el usuario, pero él/ella puede actualizar conscientemente cambiando también la ruta de importación (pr vgo puede hacer eso para él/ella).

Creo que la razón principal para no permitir v1 o v0 en la ruta de importación es garantizar que solo haya una ruta de importación para cada versión compatible de un paquete.

Sí, supongo que de hecho puedo ver ese punto para no confundir a los nuevos usuarios de una biblioteca.

Si la versión principal es v0 o v1, entonces se debe omitir el elemento del número de versión; de lo contrario, debe incluirse.

¿Puede alguien explicar el razonamiento detrás de esto? ¿Qué hago, como usuario de una biblioteca, cuando no quiero usar v1 todavía, porque introdujo un cambio importante, que estaría totalmente bien con el control de versiones semántico (nueva versión principal)?

Preferiría omitir solo la versión anterior a la versión 1, lo que indica un paquete inestable/inacabado. A partir de la versión 1, quiero poder confiar en el hecho de que obtengo una versión estable. Omitir la v1 en la ruta de importación es confuso, porque no sabe si está rastreando una biblioteca en constante cambio o una versión estable. Creo que esto tampoco funciona bien con el esquema de control de versiones semántico, donde v1 señala la primera versión estable, que se usa para distinguir claramente esa versión de las versiones 0.x.

@kaikuehne

¿Qué hago, como usuario de una biblioteca, cuando no quiero usar v1 todavía, porque introdujo un cambio importante, que estaría totalmente bien con el control de versiones semántico (nueva versión principal)?

Por lo que entendí, vgo nunca actualizará las dependencias por sí solo, ni siquiera a una versión de parche, sino que lo dejará como una decisión consciente que usted debe tomar. Entonces, si depende de la versión 0.4.5 de una biblioteca (que tiene una etiqueta), en teoría, puede seguir usándola para siempre. También podrá anclar la versión manualmente en su archivo go.mod .

¿Qué sucede si otra dependencia que uso depende del mismo paquete, pero de la versión v1? Ambos paquetes se importan utilizando la misma ruta de importación. ¿No hay un conflicto al compilarlos en el mismo binario?

Si necesitáramos que v1 también fuera parte de la ruta de importación, ambos serían tratados como paquetes diferentes, lo cual es cierto.

@kaikuehne luego se actualizaría a la versión mínima común que funciona. (a mi entender)

@kaikuehne No entiendo tu razonamiento. Está utilizando v0, por lo que presumiblemente está bien con cambios importantes; ¿Por qué sería un problema si v1 se rompe, dado que ya está usando una versión que no tiene garantía de estabilidad? Además, supongamos que en lugar de pasar de v0.1->v1.0 con un cambio importante, upstream agregaría la interrupción a v0.2 y luego lanzaría una versión 1.0 (sin interrupciones). Eso parecería estar dentro de las expectativas en torno a las versiones semánticas, pero equivaldría exactamente a la misma cantidad de trabajo para usted (sin importar el administrador de paquetes utilizado). Es decir, realmente no entiendo cómo "el autor de repente dejó de romper su API" constituye un problema que no está causado por el uso de una versión anterior a la 1.0.

Para decirlo en otras palabras: al usar v0.x, acepta que v0.(x+1) podría obligarlo a corregir su código. ¿Por qué es un problema si v0.(x+1) se llama v1.0 en su lugar?

Sobre el punto de discusión 4: Adoptar explícitamente la regla de compatibilidad de importación y "el nuevo paquete debe ser compatible con versiones anteriores del paquete anterior"...

En mi caso, tengo un paquete de seguridad https://github.com/microcosm-cc/bluemonday y recientemente (finales del año pasado) tuve un escenario en el que aprendí que una función pública no era fundamentalmente adecuada para su propósito. Así que lo eliminé.

Según esta propuesta, si elimino la función, la versión cambiará y el código inseguro/no seguro nunca se eliminará.

Para evitar eso, probablemente en su lugar logré.Fatal() dentro de la función que deseaba eliminar, simplemente para asegurarme de que el código existente no usara un punto final inseguro sino para preservar la compatibilidad.

Dado que ninguno de estos es ideal... ¿cómo prevemos las correcciones de seguridad que requieren que una función pública sea obsoleta para ser manejada? (si no sorprendiendo al desarrollador con un registro de tiempo de ejecución. ¿Fatal ()?)

Para aquellos que quieran ver la confirmación de esto: https://github.com/microcosm-cc/bluemonday/commit/a5d7ef6b249a7c01e66856b585a359970f03502c

@Merovius Gracias por la aclaración al usar las versiones 0.x. Como dijiste, no hay garantías en las que confiar cuando se usa una versión anterior a la 1.0 y que las versiones 0.x son un caso especial en semver. Si entendí correctamente, las reglas descritas en realidad no se aplican a las versiones 0.x en absoluto. Mi pregunta es si tendría sentido reflejar esta distinción también en el código, especialmente al nombrar paquetes. Por ejemplo, si un paquete solo importó paquetes sin una versión, podría ver de un vistazo que se basa en un código inestable. Si todas las importaciones contienen una versión v1, verá que utiliza versiones estables.

@buro9 La propuesta sugiere seguir aproximadamente las garantías de compatibilidad de go1, que contienen exenciones para fallas de API relacionadas con la seguridad.

@kaikuehne Gracias, eso aclara tu preocupación.

Hay una interacción de características que me preocupa (suponiendo que entiendo las cosas correctamente).

Si tiene un módulo M que usa versiones cosificadas (directorios vN literales en la fuente, no elementos de ruta de importación sintéticos derivados de etiquetas), y está creando un programa P que se basa en múltiples versiones principales de M transitivamente, ¿no es así? tiene que violar la selección de versión mínima en algunos escenarios?

Es decir, digamos que P depende de las versiones principales 2, 3 y 4 de M. Para cada versión principal de M, se especifica una versión mínima completa. Dado que las versiones de M comparten fuente con el propósito expreso de poder hacer cosas como usar de forma transparente la misma definición de tipo con alias de tipo, solo se puede incluir una copia de M para las tres versiones principales en lugar de una copia por versión principal. Cualquier elección de versión completa para una versión principal corrige la elección de la versión completa de las otras dos versiones principales y podría llevar a seleccionar una versión no mínima para una o ambas versiones principales.

¿Cómo maneja vgo esto? ¿Podría esto causar algún problema además de que a veces sea un poco menos que mínimo? (¿Como si fuera posible construir accidentalmente un conjunto de módulos que no produzcan una solución o que provoquen un bucle en el solucionador?)

@jimmyfrasche

Si está utilizando directorios de versiones principales, vgo seguirá usando etiquetas y luego solo obtendrá la carpeta de la versión correspondiente de esa etiqueta. por ejemplo, depende de las versiones 2, 3, 4. vgo verificará la etiqueta v2.nm, v3.nm, v4.nm
Y luego, desde la etiqueta v2.nm, solo obtenga la carpeta v2 y así sucesivamente. Entonces, al final, todo sigue siguiendo etiquetas.

Hice una pregunta en esta publicación de la lista de correo , pero no he visto una respuesta concreta. Lo repetiré aquí:

¿Qué sucederá con los recursos que no son de Go, como protobufs o archivos c? Disculpe si esto ya se respondió en sus publicaciones, pero usamos la ruta del proveedor para distribuir y configurar la ruta de importación para los archivos protobuf. Si bien compilaríamos los paquetes de Go con la salida de protobuf precompilada, también debemos considerar el caso de compilar nuevos paquetes de Go a partir de archivos de protobuf que dependen de las dependencias del proveedor (es decir, hace referencia a rpc.Status desde otro archivo de protobuf). Puedo proporcionar algunos ejemplos más concretos si esa descripción es demasiado densa.

Específicamente, tengo un proyecto llamado protobuild que permite asignar la importación de archivos protobuf a las ubicaciones de GOPATH. No veo cómo esta propuesta manejará la resolución de recursos en GOPATH y cómo podemos mapear eso en otros espacios de importación del compilador.

Este fue un gran problema para nosotros al trabajar con protobufs y este proyecto alivió muchos de esos problemas. Sería una pena que esto fuera completamente incompatible con la propuesta.

Una vez más, disculpas si hay algo que me he perdido.

Me encanta la propuesta. Solo me preocupa que demasiados proyectos introduzcan con frecuencia pequeños cambios de última hora entre versiones secundarias y reserven cambios de versiones principales solo para cambios de última hora muy grandes. Si los cambios de ruptura de versiones menores son frecuentes, entonces surgirán problemas de dependencia de diamantes, ya que viola la suposición de SIV. Me pregunto si incluir la versión secundaria en la declaración de importación ayudaría a que más proyectos cumplan con el contrato de cambios ininterrumpidos. Creo que las desventajas son la rotación adicional de importaciones y la actualización de versiones secundarias se vuelve más difícil (y más explícita).

Esto trae otra pregunta que tengo: ¿es fácil (hoy) con vgo determinar si tiene más de 1 versión de un paquete en una compilación? Si bien permitir dos versiones del mismo paquete es crucial para avanzar a veces, parece que la mayoría de los proyectos querrían evitar esto a menos que sea temporal debido a posibles efectos secundarios imprevistos de init. Tener una manera fácil de verificar esto puede ser útil y algunos proyectos pueden querer aplicarlo durante la verificación del código.

Solo me preocupa que demasiados proyectos introduzcan con frecuencia pequeños cambios de última hora entre versiones secundarias y reserven cambios de versiones principales solo para cambios de última hora muy grandes.

Romper el cambio es un cambio de ruptura. No puede ser pequeño o grande. Supongo que tales paquetes eventualmente serán rechazados por la comunidad por ser demasiado poco confiables y no seguir a Semver. Incluso si siguen a Semver y llegan rápidamente a un gran número mayor como 42.xx, de todos modos serán muy inconvenientes de usar. Entonces, si desea realizar muchos cambios importantes, simplemente siga usando el número principal 0. De esta manera, seguirá funcionando como el go get actual, con los mismos problemas. Si desea experimentar con la API después de lanzar una versión principal que no sea 0, mueva estos experimentos a un paquete "experimental" separado con 0 mayor para siempre e incremente la principal del paquete principal cuando haya terminado con "pequeños cambios importantes" y finalmente obtenga la siguiente API estable.

Incluir menor en la ruta de importación viola la ideología de Semver y no proporciona ninguna característica nueva sobre la inclusión de mayor.

Si bien entiendo que eso es lo que los autores deberían hacer dada la semántica de semver, mi temor es que los cambios menores entre versiones menores sean un caso común y tentador para alguien que ya pasó la versión 1. En mi experiencia anecdótica, los autores de paquetes no siga la semántica exacta de semver y, a menudo, las empresas reservan las versiones principales para fines de marketing. Así que mi apelación no es sobre lo que es ideal, sino sobre si puede ser práctico hacer ciertos cambios para lidiar mejor con la desordenada realidad humana que es Semver.

Tal vez incluso sea posible incluir opcionalmente la versión secundaria para paquetes que no obedezcan a Semver, tal vez eso arruine toda la propuesta, tendría que pensarlo más. No estoy proponiendo que esta sea una mejor manera, solo que estoy interesado en explorar más a fondo las ventajas y desventajas de incluir opcionalmente u ordenar la inclusión de la versión secundaria en las importaciones.

Es probable que sea posible generar mejores datos aquí a partir del corpus go (y una herramienta que busca cambios importantes obvios) para determinar con qué frecuencia semver se sigue mayoritariamente entre los proyectos populares existentes que usan etiquetas semver.

La propuesta de vgo permite que las versiones principales rompan con gracia los cambios de API. (Por sí mismo) no hace nada para prevenirlos.

La propuesta de vgo permite que una versión principal se refiera a otra versión principal, lo que permite una reutilización elegante del código. No hace nada para forzar eso.

La propuesta de vgo MVS permite actualizar a paquetes más nuevos. No te obliga a actualizar.


Aquí hay cosas que podemos construir con mucha mayor facilidad en un mundo vgo:

  1. Herramientas para capturar los cambios de frenado de la API antes de enviarlos a un host de módulo. Cada versión está en un zip y se puede comparar sin muchas herramientas y comandos de vcs diferentes.
  2. Registro de problemas de seguridad. Anfitrión junto con el alojamiento del módulo para agregar valor. Las herramientas pueden consultarlos de manera similar a go list ya sea de forma manual o automática, y recibir notificaciones de problemas filtrados por una consulta.

vgo lo hace más fácil al:

  • Restricción del espacio del problema (trabaje solo con archivos zip, no es necesario almacenar el historial arbitrario de git/hg/svn para hacer comparaciones de API).

    • Definición del espacio del problema (MVS, definición de versión)

  • Mecanizado de la parte de construcción.

vgo opera con un principio fundamental: un solo conjunto de entradas siempre debe construir lo mismo. Si confiamos en reconstrucciones aleatorias para detectar actualizaciones de seguridad , lo estamos haciendo mal . Como mantenedor de proyectos, algunos proyectos de Go simplemente se ejecutan durante años sin una reconstrucción. Acepto que las actualizaciones de seguridad oportunas son importantes: vgo satisface la parte de construcción de esta necesidad.

No debemos confundir lo que permite vgo con lo que es vgo.

@pbx0 No estoy seguro de si este es el lugar adecuado para tal discusión, tal vez la lista de correo sea más adecuada. En cualquier caso, suceden los cambios de ruptura sin cambiar el número principal. Incluso de vez en cuando. Semver tiene este caso respondido en las preguntas frecuentes:

Tan pronto como se dé cuenta de que ha infringido la especificación de versiones semánticas, solucione el problema y publique una nueva versión secundaria que corrija el problema y restaure la compatibilidad con versiones anteriores.

Pero creo que hay un lugar para mejorar aquí. Supongo que debería ser lo suficientemente fácil implementar un verificador de API automatizado (tal vez ya exista uno), que tomará todos los paquetes enumerados en godoc.org y verificará periódicamente si hay nuevas versiones, y en caso de que se detecte una nueva versión, verificar si la nueva versión es compatible con la anterior. API de la versión en caso de que use etiquetas semver y no se modificó la principal. Luego intente ponerse en contacto con el autor en caso de que se detecte un cambio incompatible, tal vez problemas de apertura automática en github o use el correo electrónico de la cuenta de github. Esto no cubrirá todos los casos posibles, pero puede ser muy útil para la comunidad.

Creo firmemente en usar rutas para alcanzar versiones principales y quería expresar mi apoyo, FWIW.

Hace un año, creía que poner versiones en rutas de importación como esta era feo, indeseable y probablemente evitable. Pero durante el año pasado, llegué a comprender cuánta claridad y simplicidad aportan al sistema.

Hace casi veinte años, necesitaba un VCS para mi startup y probé unos diez diferentes. Inmediatamente descarté Perforce porque exponía ramas usando directorios. Entonces, la rama v2 sería todo el mismo código, pero en una carpeta v2. Odiaba esta idea. Pero después de ejecutar pilotos con los otros nueve, descubrí que a menudo quería tener ambas versiones de una rama en mi sistema de archivos local, y resultó que Perforce lo hizo trivialmente fácil, mientras que los otros lo hicieron sorprendentemente complicado. El sistema de archivos es nuestra metáfora de contención. Usémoslo.

De la propuesta:

Defina un esquema de URL para obtener módulos de Go desde servidores proxy, que se utiliza para instalar módulos con nombres de dominio personalizados y también cuando se establece la variable de entorno $GOPROXY. Este último permite a empresas y particulares enviar todas las solicitudes de descarga de módulos a través de un proxy por motivos de seguridad, disponibilidad u otros.

He mencionado esto en otra parte, pero mi mayor preocupación con la propuesta es que parece descartar (o al menos no aborda) una de las mayores fortalezas de la venta actual: código siempre disponible y compilaciones perfectamente reproducibles. No creo que el sistema proxy propuesto aborde o reemplace adecuadamente estas fortalezas.

Un proyecto que utiliza la venta hoy en día solo requiere la cadena de herramientas Go y Git (u otro sistema de control de versiones). Solo existe un único punto de falla: el repositorio de git. Una vez que se verifica el código, se puede compilar y reconstruir perfectamente sin necesidad de volver a tocar la red, una consideración de seguridad importante. Para la mayoría de nosotros, un proyecto de venta no requiere infraestructura adicional, solo su computadora local y una cuenta gratuita de GitHub.

La dependencia de vgo en los proxies introduce una sobrecarga de infraestructura no trivial que creo que no se enfatiza lo suficiente. La nueva infraestructura debe ser aprovisionada, implementada, mantenida y monitoreada. Esto puede ser razonable para las organizaciones de software, pero es una carga para los individuos y los proyectos de código abierto descentralizados. Además, cosas como CI a menudo se subcontratan a terceros como Travis CI, que no se ejecutan en la misma infraestructura que el entorno de desarrollo de la empresa. Esto dificulta la reutilización de la infraestructura de proxy.

Otros lenguajes permiten el uso de servidores proxy de almacenamiento en caché. Python es con el que tengo más experiencia y, según mi experiencia, rara vez se usa debido a la sobrecarga de configurar uno. Tal vez el proyecto Go pueda hacer esto más simple, pero si no es el predeterminado, encontraremos que se usa con menos frecuencia y la disponibilidad de compilaciones de Go en la naturaleza disminuirá sustancialmente. El impacto del evento NPM del panel izquierdo es un excelente caso de estudio a este respecto.

Si el módulo y el sistema de proxy nos permiten verificar las dependencias junto con el código de nuestro propio proyecto (similar a la venta actual, pero no necesariamente la misma implementación) y la implementación del proxy vgo puede usarlo, eso resolvería mis preocupaciones. Pero si esa es la intención, creo que debe abordarse mucho más en la propuesta.

@joeshaw Podrá continuar usando un directorio de proveedores para crear una compilación independiente.

De la propuesta:

No permitir el uso de directorios de proveedores, excepto en un uso limitado: un directorio de proveedores en la parte superior del árbol de archivos del módulo de nivel superior que se está compilando aún se aplica a la compilación, para continuar permitiendo repositorios de aplicaciones autónomos. (Ignorar los directorios de otros proveedores garantiza que Go regrese a las compilaciones en las que cada ruta de importación tiene el mismo significado en toda la compilación y establece que solo se usa una copia de un paquete con una ruta de importación determinada en una compilación determinada).

Un proyecto que utiliza la venta hoy en día solo requiere la cadena de herramientas Go y Git (u otro sistema de control de versiones). Solo existe un único punto de falla: el repositorio de git.

Hoy en día, si está alojando paquetes bajo su propio dominio, necesita a) alojar el repositorio git yb) servir las etiquetas <meta> necesarias para que go-get lo encuentre. En el futuro, debe a) proporcionar los archivos .zip y .json necesarios para que vgo obtenga el código. Parece que hay menos puntos de fallas y se necesita menos infraestructura para el hospedaje puro. Por supuesto, aún necesita alojar el repositorio para el desarrollo, pero eso no solo nos lleva al mismo nivel que antes, en el peor de los casos, sino que el repositorio en sí también requiere un alojamiento mucho menos escalable y confiable, ya que solo lo usan las personas que realmente desarrollan.

Entonces, para las importaciones de artículos de tocador, no parece haber mucha diferencia en términos de gastos generales.

Si, OTOH, no está utilizando vanity imports, está ignorando toda la infraestructura que github está ejecutando para usted. Así que esto no parece ser una comparación de manzanas con manzanas: la única manera de salir victorioso es dejando que otras personas resuelvan los problemas difíciles. Pero no hay nada que te impida hacerlo en el futuro. AIUI Microsoft y otros ya se han ofrecido como voluntarios para invertir horas de ingeniería y capacidad de servicio en esta tarea. Espero que en el futuro, el esfuerzo de hospedar paquetes de Go esté más o menos limitado por el esfuerzo de hospedar paquetes npm o gemas o cajas: tiene un repositorio de github y luego hace clic en el botón "hacer que esté disponible" en algunos centralmente servicio gestionado para alojar los zips.

vgo en proxies

Personalmente, no me gusta la palabra "proxy" para lo que hace la infraestructura requerida. "Espejo" parece más apropiado. El espejo puede implementarse como un proxy, pero también puede ser solo un montón de archivos servidos por un servidor web de su elección, ocultos detrás de cloudflare para una escalabilidad y un tiempo de actividad aproximadamente infinitos.

Otros lenguajes permiten el uso de servidores proxy de almacenamiento en caché.

Yo diría que otros idiomas sirven como un modelo perfecto de por qué esto no es realmente un problema. Tienden a confiar en el alojamiento centralizado para que sus paquetes alojen paquetes: vgo no solo admite este modelo extremadamente bien, sino que también lo hace opcional (para que obtenga todas las ventajas sin ninguna de las desventajas) y muy simple implementar, escalar y operar.


En mi opinión, si compara directamente lo que sucede antes y después y en Go y en otros idiomas, debe quedar claro que hay muchas equivalencias 1:1. Y la única razón por la que parece que habrá más esfuerzo en el futuro es porque damos por sentada la infraestructura existente y vemos que la nueva infraestructura aún no existe. Pero no creo que tengamos buenas razones para dudar de que así sea.

Entonces, para las importaciones de artículos de tocador, no parece haber mucha diferencia en términos de gastos generales.

Cierto, pero la _gran_ minoría de paquetes usa dominios de vanidad, así que no creo que sea un fuerte contrapunto. (También tengo otros problemas prácticos con los dominios de vanidad, que es que su disponibilidad tiende a ser _mucho peor_ que simplemente usar GitHub).

Si, OTOH, no está utilizando vanity imports, está ignorando toda la infraestructura que github está ejecutando para usted.

¡Sí exactamente! Siento que esto hace mi punto para mí. Obtiene todo ese maravilloso trabajo en infraestructura y mantenimiento de tiempo de actividad de forma gratuita o a un costo razonable. Más importante aún, no involucra nada de su propio tiempo.

Si GitHub terminó ejecutando un espejo compatible con vgo , entonces tal vez esto sea menos preocupante, aunque me gusta la elegancia de una sola búsqueda de Git, una acción atómica desde la perspectiva del usuario, que contiene todo el código. Necesito construir un proyecto.

Yo diría que otros idiomas sirven como un modelo perfecto de por qué esto no es realmente un problema. Tienden a confiar en el alojamiento centralizado para que sus paquetes alojen paquetes: vgo no solo admite este modelo extremadamente bien, sino que también lo hace opcional (para que obtenga todas las ventajas sin ninguna de las desventajas) y muy simple de implementar, escalar y funcionar.

El problema es que esto agrega puntos únicos de falla (SPOF) a la construcción de un proyecto. El código vivirá en un VCS pase lo que pase (y probablemente en GitHub), así que ese es un SPOF. En otros idiomas, un repositorio centralizado es un segundo SPOF. Para Go, cada ruta de importación es un SPOF adicional (github.com, golang.org, honnef.co, rsc.io, etc.) y el aumento de los SPOF reduce la disponibilidad general.

Ejecutar un espejo puede reducir eso a dos, claro, pero es una infraestructura que, en mi opinión, no necesita existir. Vender sus dependencias (o tener un espejo local en disco) reduce esto a solo uno: su VCS.

En cualquier caso, esto puede ser un punto discutible. Originalmente, no entendía la parte de la propuesta sobre el directorio vendor de nivel superior que parecería resolver mis principales preocupaciones, gracias por señalarlo, @kardianos , aunque es una ruptura clara con el antiguo sistema de venta podría ser mejor.

Me alegro de que el "nivel superior vendor " siga siendo una configuración compatible porque me encanta git grep .

Ejecutar un espejo puede reducir eso a dos, claro, pero es una infraestructura que, en mi opinión, no necesita existir.

Desarrollador empresarial aquí. Tal vez no seamos el grupo demográfico objetivo, pero nos gustaría usar Go. No puedo ver que eso suceda sin que tengamos un espejo dentro de nuestra empresa, como lo hacemos con java y javascript, para garantizar que todo lo que construimos hoy pueda construirse mañana.

Desarrollador empresarial aquí. Tal vez no seamos el grupo demográfico objetivo, pero nos gustaría usar Go. No puedo ver que eso suceda sin que tengamos un espejo dentro de nuestra empresa, como lo hacemos con java y javascript, para garantizar que todo lo que construimos hoy pueda construirse mañana.

@jamiethermo ¿La venta no aborda eso para usted hoy?

El soporte para proxies o espejos está bien, y si eso ayuda a la adopción de Go, estoy totalmente de acuerdo. Mi preocupación eran los espejos como reemplazo de los árboles de origen autónomos locales (lo que llamamos venta hoy en día).

@joeshaw

¿La venta no aborda eso para usted hoy?

Bueno, debo confesar ignorancia y cierta frustración con "cómo debo organizar mi código". Por "árbol de fuentes autónomo", ¿quiere decir que tengo un repositorio git gigante que contiene todo mi código, además de todo el código en el árbol de proveedores? Entonces, ¿no necesito un espejo porque verifiqué todo ese otro código en mi propio repositorio?

Con respecto a "cómo debo organizar mi código", esta página, Cómo escribir código Go , instruye sobre la estructura del directorio, pero no menciona la venta.

Adopte el control de versiones de importación semántica, en el que cada versión principal tiene una ruta de importación distinta. Específicamente, una ruta de importación contiene una ruta de módulo, un número de versión y la ruta a un paquete específico dentro del módulo. Si la versión principal es v0 o v1 , entonces se debe omitir el elemento del número de versión; de lo contrario, debe incluirse.

Los paquetes importados como my/thing/sub/pkg , my/thing/v2/sub/pkg y my/thing/v3/sub/pkg provienen de las versiones principales v1 , v2 y v3 del módulo my/thing, pero la compilación los trata simplemente como tres paquetes diferentes.

my/thing/sub/pkg también puede ser v0.

Seguí el recorrido . El ejemplo está construido fuera del árbol GOPATH y funciona, mientras que dep init vomita en esa situación. Trabajo con, creo, 80 equipos ahora, y sería muy bueno no tener que tener un árbol gigante. (Mientras estaba escribiendo esto, alguien se acercó con su computadora portátil y con el ceño fruncido, y "Tengo este error realmente extraño...")

@joeshaw

Obtiene todo ese maravilloso trabajo en infraestructura y mantenimiento de tiempo de actividad de forma gratuita o a un costo razonable.

Lo expresé mal. Quise decir "si afirma que solía necesitar menos infraestructura si no está usando vanity imports, está ignorando toda la infraestructura que github ejecuta para usted". Quería señalar que la infraestructura todavía está allí y todavía necesita funcionar. Y puede seguir ejecutándose para usted en el futuro también.

Por lo tanto, su preocupación se abordaría en lo que considero el escenario más probable: que un organismo financiado (actualmente, Microsoft se perfila como tal) esté alojando los archivos zip.

aunque me gusta la elegancia de una sola búsqueda de Git: una acción atómica desde la perspectiva del usuario

vgo get es tanto una acción atómica y hace menos trabajo, de la misma naturaleza (solicitudes HTTP) que es más fácil de entender.

El problema es que esto agrega puntos únicos de falla (SPOF) a la construcción de un proyecto.

Entonces, ¿dónde está mi último comentario incorrecto? Porque me parece bastante obvio que la cantidad de puntos de falla es, en todo caso, menor , son más simples, más fáciles de escalar y más baratos de ejecutar.

En otros idiomas, un repositorio centralizado es un segundo SPOF. Para Go, cada ruta de importación es un SPOF adicional (github.com, golang.org, honnef.co, rsc.io, etc.) y el aumento de los SPOF reduce la disponibilidad general.

Creo que esto está demasiado simplificado. Si aloja su código en un espejo que se cae, aún puede desarrollar (github todavía está activo) y los usuarios aún pueden instalar (usando un espejo diferente). No importa el host de una de sus dependencias, ya que refleja sus dependencias. Si no confía en que el espejo administrado por la comunidad "centralizado" permanezca activo, puede ejecutar el suyo propio o pagarle a alguien para que lo haga, sin diferencia para los usuarios, lo que le brinda control total sobre cuánto se ve afectado por el tiempo de inactividad de el repositorio centralizado.

Ninguna de las cosas que mencionas en realidad es un SPOF, ya que aún obtienes al menos una operación degradada. Agregue a eso, que los espejos reales son comparativamente triviales para operar (ya que son solo servidores HTTP sin estado) y no estoy convencido de que la confiabilidad y la disponibilidad disminuyan significativamente.

Y FTR, en este momento su git-hosting es un SPOF: si su git-host no funciona, los usuarios no pueden instalar y usted no puede desarrollar.

Ejecutar un espejo puede reducir eso a dos, claro, pero es una infraestructura que, en mi opinión, no necesita existir.

Y mi punto anterior (mal expresado) fue que ya lo hace :) Simplemente estás a) ignorando que sucede ahora yb) asumiendo que no sucederá en el futuro :)

Para dar una perspectiva diferente:

  • estamos creando muchos proyectos Go con nuestro administrador de componentes de software multilingüe en todo el sistema (rpm/dnf en Fedora, Centos y RHEL)
  • nos permite usar muchos de los mismos trucos que la propuesta vgo, jugando con el espacio de nombres del componente de la capa rpm (por lo general, renombrando un proyecto en el nivel del espacio de nombres rpm de proyecto a compat-project-x para permitir distinguir entre versiones incompatibles del misma ruta de importación, exactamente como lo hará vgo).
  • estos trucos son definitivamente útiles para ayudar a construir proyectos Go complejos
  • aunque no es tan completo y robusto como hacerlo a nivel de idioma
  • preferimos transmitir restricciones de lenguaje a rpm/dnf que agregar una superposición de restricciones rpm/dnf sobre el código original.
  • estamos bastante hartos de todas las soluciones alternativas del sistema de archivos que se necesitan actualmente para convencer a las herramientas Go de que busquen las fuentes del proyecto Go. El GOPATH físico no se perderá en absoluto.

Por lo tanto, estamos encantados con vgo y esperamos que se implemente pronto (lo necesitábamos hace años).

Dicho esto, nuestro uso de flujos de trabajo similares a vgo expuso las siguientes dificultades.

La propuesta de vgo se felicita por haber hecho innecesarios los makefiles. Esto no es completamente cierto.

  • muchos proyectos de Go se han enamorado de los archivos go autogenerados y no existe una forma estándar de ir a demanda para regenerarlos o para expresar lo que la generación necesita para tener éxito
  • es tan malo que muchos proyectos tienen que enviarse con archivos pregenerados (a veces creando repositorios de archivos pregenerados completos y separados)
  • esos archivos son una gran fuente de incompatibilidades de versión. Los humanos se preocupan por escribir código que no necesite cambiarse todos los días cuando se exponga a nuevas versiones de dependencia. Los archivos OTOH generados automáticamente a menudo están estrechamente vinculados a un entorno de generación exacto, porque los autores de herramientas generadoras asumen que solo los regenerará según sea necesario.
  • para que vgo tenga éxito, necesita una forma de identificar esos archivos, eliminarlos de los módulos .zip y expresar cómo regenerarlos para los usuarios de los módulos .zip

Esto se ve agravado por la regla actual de "todo debe estar en GOPATH"

  • todo no puede estar en GOPATH cuando la generación depende de protofiles publicados fuera de GOPATH por proyectos multilenguaje
  • la cadena de herramientas Go necesita aprender a leer recursos fuera de su GOPATH
  • la cadena de herramientas de Go necesita aprender a publicar recursos fuera de GOPATH, cuando están expuestos a proyectos no necesariamente escritos en Go
  • la solución actual de duplicación de recursos en copias dentro de GOPATH es otra fuente de incompatibilidades de versión
  • todos no copiarán los mismos archivos al mismo tiempo
  • a veces los proyectos se copian de varias fuentes, creando mezclas únicas.
  • cada proyecto tendrá control de calidad en su propia copia, lo que hace que la composición del proyecto Go sea peligrosa
  • el solucionador de la versión vgo no funcionará según lo previsto si calcula las relaciones entre las versiones de código pero ignora las relaciones entre las versiones de recursos.
  • vgo necesita hacer copias privadas de las cosas publicadas fuera de GOPATH innecesarias para evitar una explosión de versiones de módulos incompatibles.

Muchos proyectos han explotado la regla "cada directorio Go es un paquete separado" para publicar proyectos con código incompatible o completamente roto en subdirectorios separados

  • muchos otros proyectos de Go han usado la misma regla para seleccionar subdirectorios específicos y usarlos en un contexto incompatible con las pruebas unitarias y el control de calidad del proyecto original.
  • que "funciona" y produce "compilaciones reproducibles" siempre que no haya cambios en el proyecto original o en el consumidor del proyecto que haga uso de alguna otra parte del proyecto original. Cuando eso sucede, todo el castillo de arena se derrumba bajo la deuda técnica acumulada,
  • ve proyectos que se niegan a actualizar a versiones más nuevas del proyecto porque eso requiere limpiar sus usos indebidos anteriores de otros proyectos.
  • tienes una extraña esquizofrenia en la que los proyectos de Go se consideran no responsables de los errores en las bases de código que reutilizan y, al mismo tiempo, se niegan a aplicar las correcciones publicadas por esas mismas bases de código (supongo que todos somos humanos y la desagradable negación de la realidad está programada). en el cerebro humano)
  • las correcciones no se propagan, y todo está "bien" hasta que detecta los errores que requirieron las correcciones en primer lugar o las pruebas unitarias que fueron invalidadas por la selección selectiva.
  • un verificador de seguridad automatizado que comparara el estado de seguridad de los proyectos, con el estado de seguridad de los mismos proyectos dentro de los directorios del proveedor, tendría un día de campo
  • cuanto más grande es el proyecto, más probable es que tenga tales bombas de relojería escondidas dentro de su proveedor
  • al definir claramente los límites del proyecto dentro de los módulos zip, vgo pondrá fin a tales prácticas
  • sin embargo, también implicará una limpieza importante de muchas bases de código de Go.
  • para que vgo tenga éxito, debe proporcionar herramientas para ayudar a los proyectos Go existentes a refactorizar y dividir su base de código en módulos que tengan sentido desde el punto de vista de la compatibilidad del software. De lo contrario, los proyectos que usan vgo producirán restricciones irreconciliables o simplemente bloquearán el statu quo (lo que funciona para el código existente, pero es terrible desde el punto de vista de la evolución del código).

La práctica actual de exponer todo el código base de Go en un solo árbol GOPATH con pequeños límites entre proyectos ha producido efectos secundarios nocivos de un POW de ingeniería de software.

  • el código no está comprometido en el proyecto donde tiene sentido técnico sino en el repositorio más conveniente para el autor del código (el repositorio al que tiene acceso)
  • Los proyectos Go se desangran entre sí, con partes de un proyecto dependiendo de partes de otro proyecto, y parte de este otro proyecto dependiendo del proyecto original.
  • que efectivamente produce gráficos restringidos de versión bloqueada donde no puede mover una parte sin mover todas las demás
  • nadie tiene los recursos para cambiar a todos los demás en una sola operación
  • los proyectos se estancan y dejan de progresar
  • usar módulos con límites claros y tratar de hacer explícitas las restricciones de versión entre módulos expondrá esas situaciones
  • eso será enormemente impopular (aunque el problema existe hoy, oculto bajo el velo de la venta)
  • con bastante frecuencia, no se trata solo de separar un subdirectorio: las dependencias del proyecto problemático pueden ocurrir en un árbol de directorios A/B/C/D en el nivel A y D, pero no en B y C.
  • para que vgo tenga éxito, debe proporcionar herramientas para ayudar a los proyectos de Go existentes a refactorizar y dividir sus bases de código en módulos separados que siguen líneas gráficas de dependencia

Testfing/fixtures, example y testdata son otra lata de gusanos, con sus propias dependencias y necesidades de versión de dependencia.

  • deben aislarse de una forma u otra en módulos separados o sus necesidades envenenarán la resolución de la versión del solucionador
  • si ignora sus necesidades, efectivamente decide que nadie más que el proyecto original ejecutará pruebas unitarias
  • esto es bastante peligroso cuando permite actualizaciones de versión. Los problemas sucederán. Necesitas detectarlos
  • las pruebas de integración que dependen no solo de algún otro código, sino de un entorno específico que nadie más que el proyecto original puede replicar (por ejemplo, un servidor o sitio web específico para hablar), probablemente necesiten un aislamiento específico

Probablemente he olvidado muchas más cosas, pero esas son las más críticas.

Finalmente:

  • Los proyectos Go no viven aislados
  • algunos proyectos de Go publican conectores a otros idiomas
  • algunos proyectos en otros idiomas publican conectores Go
  • eso hace que tratar a semver de una manera diferente a esos otros idiomas sea un problema.
  • no puede tener todo, excepto la parte Go, actualizándose a la última versión secundaria cuando se lanza un proyecto en varios idiomas.
  • eso sería un infierno para un prisionero de guerra de gestión operativa.
  • la actualización automática a la última subversión juega un papel muy importante en la simplificación de los gráficos de restricciones de software al hacer que todos aspiren versiones anteriores (el beneficio es técnico, el mecanismo es social).
  • las reconstrucciones de alta fidelidad son similares a los sitios web con píxeles perfectos. Parecen una idea obviamente buena, recompensan el ego del autor original, pero son un PITA para cualquiera que realmente intente usar el resultado porque no son evolutivos ni adaptables al contexto local (no original).

En servidores proxy:

para facilitar la depuración, $GOPROXY puede incluso ser un archivo:/// URL que apunte a un árbol local.

Haga que funcione con un archivo: /// de https:/// URL que apunte a un directorio que contenga módulos de terceros en formato zip (y excluya todo lo demás)

Esa es la forma más sencilla para que una entidad coordine el trabajo de varios equipos de desarrollo que se basan en subconjuntos de la misma lista de proyectos de terceros: tener una persona de control de calidad/legal/seguridad responsable de examinar los "buenos" lanzamientos de terceros y desplegarlos en un directorio común y hacer que todos los demás tengan su trabajo dependiendo de los módulos disponibles en este directorio común.

De esa manera, está seguro de que nadie comienza a trabajar en una revolución incompatible con el trabajo de los demás, nadie se queda en una revolución con errores o peligrosa ya identificada por otro equipo, y sus estaciones de desarrollo no están esperando continuamente la descarga de las mismas copias. de software ya disponible localmente.

@Merovius No estoy de acuerdo, pero creo que nos estamos desviando del tema y no queremos atascar la discusión del problema. Sin embargo, estoy feliz de seguir en un medio diferente. (Mi correo electrónico está en mi perfil de github y soy joeshaw en la holgura de Gophers).

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

¿Qué zona horaria se usa para la marca de tiempo en la pseudoversión (v0.0.0-yyyymmddhhmmss-commit)?

Como anotó en su edición, UTC. Pero tenga en cuenta también que nunca tendrá que escribirlos. Simplemente puede escribir un hash de confirmación de git (prefijo) y vgo calculará y sustituirá la pseudo-versión correcta.

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

¿Abordará las dependencias de C?

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

¿Qué sucederá con los recursos que no son de Go, como protobufs o archivos c?

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

La propuesta de vgo se felicita por haber hecho innecesarios los makefiles. Esto no es completamente cierto. [Discusión del código generado.]

El desarrollo Non-Go sigue sin ser un objetivo del comando go , por lo que no habrá soporte para administrar bibliotecas C y demás, ni habrá soporte explícito para búferes de protocolo.

Dicho esto, ciertamente entendemos que el uso de búferes de protocolo con Go es demasiado difícil, y nos gustaría ver que se aborde por separado.

En cuanto al código generado de manera más general, la respuesta es un verdadero sistema de compilación multilingüe, específicamente porque no queremos que todos los usuarios necesiten tener instalados los generadores correctos. Es mejor que el autor ejecute los generadores y verifique el resultado.

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

Sé que la rama predeterminada se puede cambiar de maestra a v2, pero esto aún me deja con la tarea de actualizarla cada vez que publique una nueva versión principal. Personalmente, preferiría tener un maestro y una rama v1, pero no estoy seguro de cómo se ajustaría exactamente a la propuesta.

Como @AlexRouSg y tal vez otros señalaron, puedes hacer esto. Sólo quería confirmar sus respuestas. También agregaré esto a las preguntas frecuentes.

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

Aunque esto funciona ahora, ¿es intencionado?

Absolutamente sí.

@jamiethermo , muchas gracias por comentar sobre Perforce y sucursales en diferentes directorios. Me había olvidado de esa función, pero tal vez eso fue lo que me convenció de que era importante permitir vgo.

Ha habido una buena discusión a partir de https://github.com/golang/go/issues/24301#issuecomment -376925845 sobre proveedores versus proxies. Hay claramente dos conjuntos distintos de preocupaciones aquí.

Los desarrolladores de código abierto tienden a querer evitar depender de la infraestructura, por lo que quieren la venta, como escribió @joeshaw . Para confirmar, lo mantendremos funcionando, de forma limitada (solo el directorio de proveedores en el nivel superior del módulo de destino general donde ejecuta los comandos go).

Los desarrolladores empresariales no tienen ningún problema en confiar en la infraestructura, que es solo otro costo, especialmente si genera una reducción de costos mayor, como no duplicar todo el código de su proveedor en cada repositorio y tener que dedicar tiempo a mantenerlo todo sincronizado. Esencialmente, todas las empresas con las que hemos hablado quieren proxies/espejos, no proveedores, como pidió @jamiethermo . Nos aseguraremos de que eso también funcione.

También queremos construir una red espejo compartida en la que los desarrolladores tengan razones para confiar, de modo que todos los desarrolladores de código abierto no sientan que deben ser proveedores. Pero eso es más tarde. Primero, vgo debe convertirse en go.

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

Haga que funcione con un archivo: /// de https:/// URL que apunte a un directorio que contenga módulos de terceros en formato zip (y excluya todo lo demás)

No estoy exactamente seguro de lo que está pidiendo al decir "excluir todo lo demás". Si se establece $GOPROXY, vgo le pregunta a ese proxy. Nunca vuelve a caer en ningún otro lugar. Ese proxy puede ser atendido por un árbol de archivos estáticos, que en su mayoría son módulos de terceros en formato zip. Sin embargo, el árbol de archivos también debe contener algunos otros archivos de metadatos para la navegación y la búsqueda. Esos archivos adicionales son inevitables, ya que HTTP no nos brinda una forma estándar de hacer cosas como listas de directorios.

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

Wow, ese es un comentario largo. Creo que estoy de acuerdo con la mayor parte de lo que escribiste. Quiero responder a la última viñeta de tu publicación:

  • las reconstrucciones de alta fidelidad son similares a los sitios web con píxeles perfectos. Parecen una idea obviamente buena, recompensan el ego del autor original, pero son un PITA para cualquiera que realmente intente usar el resultado porque no son evolutivos ni adaptables al contexto local (no original).

Creo que diría que los archivos de bloqueo son como sitios web con píxeles perfectos. Las compilaciones de alta fidelidad, por el contrario, se degradan con gracia a medida que cambia el contexto. De forma predeterminada, una compilación utilizará, por ejemplo, B 1.2 y C 1.4. Pero luego, si es parte de una compilación más grande que necesita B 1.3, está bien, se llevará bien con B 1.3 pero mantendrá C 1.4 (incluso si existen más nuevos) en ausencia de un requisito concreto para actualizar. Así que las construcciones de alta fidelidad son lo mejor de ambos mundos: fiel al original en la medida de lo posible, pero sin insistir en la perfección de píxeles cuando eso no es posible.

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

@rsc Me gustaría pedirle que sea más preciso sobre la hoja de ruta y lo que debemos hacer ahora.
¿Seguirá la política de Go y la característica de congelación de vgo a los 3 meses (2 ahora)?

Vgo es un prototipo y nunca se lanzará por sí solo. No está sujeto a la congelación o cualquier otra cosa. Pero esta propuesta es trasladar las ideas y la mayor parte del código al cmd/go principal. Como parte del lanzamiento, cmd/go ciertamente está sujeto a la congelación. Debido a que es opcional y debido a que el código específico de vgo está bastante bien aislado del resto de la operación del comando go, el trabajo en partes específicas de vgo tiene un riesgo bastante bajo y podría continuar durante un par de semanas. en la congelación. En este momento estoy centrado en la discusión de la propuesta y los ajustes. Una vez que la propuesta parezca estar en buena forma sin problemas significativos, pasaremos a mover el código a cmd/go.

¿Deberíamos ir ahora con nuestro bastón de peregrino pidiendo a todos los mantenedores de libs que agreguen un archivo go.mod o deberíamos esperar a que la propuesta sea aceptada oficialmente (para asegurarnos de que el nombre y la sintaxis no cambien)?

Creo que es probable que cambie la sintaxis de go.mod (ver este problema). Pero como señalé en la propuesta, seguiremos aceptando sintaxis antiguas para siempre, y vgo solo actualizará los archivos existentes, por lo que no es gran cosa. Dicho esto, no intentaría enviar PR a todas las bibliotecas que pueda encontrar hasta que el código llegue a la copia de desarrollo de cmd/go.

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

¿Es fácil (hoy) con vgo determinar si tiene más de 1 versión de un paquete en una compilación?

Lo más fácil de hacer hoy es compilar el binario y luego ejecutar goversion -m en él (consulte https://research.swtch.com/vgo-repro). Cuando tenemos una lista de tareas más general con reconocimiento de módulos, debería poder hacer lo mismo sin construir primero el binario.

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

[¿Puedo hacer un cambio de seguridad incompatible con versiones anteriores, como microcosm-cc/ bluemonday@a5d7ef6? ]

Como dijo @Merovius , si vamos a adoptar las pautas de compatibilidad de Go 1 , los cambios de seguridad se permiten explícitamente sin cambiar la versión principal.

Dicho esto, incluso cuando tenga que hacer algo por la seguridad, probablemente debería esforzarse por lograr una interrupción mínima. Podría decirse que la confirmación a la que se vinculó es más perturbadora de lo necesario y, en una situación futura, lo alentaría a abordar dicho cambio desde el punto de vista de "¿cómo interrumpo la menor cantidad de clientes posible y al mismo tiempo elimino el problema de seguridad? "

Por ejemplo, no elimine una función. En su lugar, haga que la función entre en pánico o registre. Solo es fatal si se llama incorrectamente.

En este caso, en lugar de eliminar AllowDocType, lo habría conservado y seguramente continuaría aceptando AllowDocType(false), ya que esa es la configuración segura. Si alguien hubiera escrito un contenedor para su biblioteca, tal vez como un programa de línea de comandos con un indicador -allowdoctype, al menos los usos del programa sin ese indicador continuarían funcionando.

Y luego, más allá de eso, parece que la preocupación era que el tipo de documento no estaba verificado por completo, pero probablemente habría realizado una verificación mínima para mantener los usos más comunes funcionando, y luego rechazaría otros de manera conservadora. Por ejemplo, al menos, habría seguido permitiendo y tal vez también me hubiera molestado en permitir ..> con cadenas entre comillas sin &#<>\ caracteres.

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

[Preocupaciones acerca de no recibir actualizaciones rápidamente.]

Realmente creo que sucederá lo contrario, que los programas podrían estar más actualizados, ya que en la selección de versión mínima es _imposible_ que una dependencia evite que la compilación general se actualice a una versión más nueva.

Lo que escribió @Merovius en https://github.com/golang/go/issues/24301#issuecomment -375992900 me parece perfecto. El punto clave es que solo obtiene actualizaciones cuando las solicita, por lo que las cosas (potencialmente) se rompen solo cuando las espera y están listas para probar, depurar, etc. Tiene que solicitarlos, pero no mucho más a menudo que en otros sistemas con archivos de bloqueo. Y también queremos que sea más fácil mostrar advertencias como "estás construyendo con una versión obsoleta/insegura". Pero es importante no solo actualizar en silencio como un efecto secundario de las operaciones de no actualización.

También se agregó a las preguntas frecuentes.

Gracias a todos por la gran discusión hasta ahora y por responder las preguntas de los demás. Respuestas realmente geniales de mucha gente, pero un agradecimiento especial a @Merovius y @kardianos. Actualicé las preguntas frecuentes https://github.com/golang/go/issues/24301#issuecomment -371228664 y el Resumen de discusión https://github.com/golang/go/issues/24301#issuecomment -371228742. Hay tres preguntas importantes aún sin respuesta (dicen TODO en el resumen), en las que trabajaré a continuación. :-)

@rsc , #24057 tiene una discusión sobre el uso de tar en lugar de zip.

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

Si el soporte para go get, tal como lo conocemos hoy, quedará obsoleto y finalmente se eliminará, ¿cuál es la forma recomendada de obtener e instalar (sin etiquetar) los archivos binarios de Go?

Seguirá siendo ir a buscar. Si el repositorio del binario no está etiquetado, go get usará la última confirmación. Pero realmente se debe alentar a las personas que publican binarios a etiquetar los repositorios que los contienen de la misma manera que los repositorios que contienen bibliotecas (o una combinación).

Si $GOPATH está en desuso, ¿dónde se instalarán estos archivos binarios?

Ya no tiene que trabajar en $GOPATH, pero el código todavía se escribe en el primer directorio que aparece en $GOPATH: es el caché de origen, consulte $GOPATH/src/v después de usar vgo. Los binarios se instalan en $GOPATH/bin. Desde hace algunos lanzamientos, no es necesario configurar $GOPATH; tiene un valor predeterminado, $HOME/go. Entonces, lo que debería suceder es que los desarrolladores dejen de preocuparse por configurar $GOPATH o incluso por saber qué es, y simplemente sepan que sus archivos binarios están en $HOME/go/bin. Pueden usar $GOBIN para anular esa ubicación.

@dsnet , gracias, agregué un enlace en el resumen de la discusión. Mantengamos esa discusión por ahí.

Si se establece $GOPROXY, vgo le pregunta a ese proxy. Nunca vuelve a caer en ningún otro lugar. Ese proxy puede ser atendido por un árbol de archivos estáticos, que en su mayoría son módulos de terceros en formato zip. Sin embargo, el árbol de archivos también debe contener algunos otros archivos de metadatos para la navegación y la búsqueda. Esos archivos adicionales son inevitables, ya que HTTP no nos brinda una forma estándar de hacer cosas como listas de directorios.

Mientras los módulos originales se mantengan en formato zip, eliminando cualquier tentación de manipularlos, y el indexador sea robusto y liviano, está bien.

Aunque las restricciones de listado no se aplican a archivos y utilidades como lftp han podido listar directorios http durante años (no importa si no es estándar si funciona en los principales servidores http). Por lo tanto, una operación sin índice probablemente sea posible y preferible para las pequeñas entidades que no deseen invertir en infraestructura. yum/dnf/zipper también se basa en índices personalizados y obtener un directorio compartido indexado no siempre es tan simple como puede pensar en algunas organizaciones.

Los desarrolladores de código abierto tienden a querer evitar depender de la infraestructura, por lo que quieren proveedores, como escribió @joeshaw

No realmente, los desarrolladores de código abierto en su mayoría quieren que todo el proceso sea abierto y transparente, y no tener que depender de los buenos deseos de otra persona. Por lo tanto, la infraestructura está perfectamente bien siempre que sea de código abierto y fácil y económica de implementar localmente. Confiar en grandes sitios propietarios de blackbox como github claramente no entra en esta categoría, pero eso no es lo mismo que infra. La gente de código abierto hizo espejos décadas antes que los demás. Lo que no aceptarán son espejos cerrados y costosos de configurar (en términos de código abierto, el costo se mide en tiempo humano)

Se aprecia la naturaleza abierta, fácil y barata de la venta, el proceso de venta en sí mismo y la forma en que fomenta la fosilización progresiva de bases de código en versiones obsoletas de código de terceros, no tanto.

Los desarrolladores empresariales no tienen ningún problema en confiar en la infraestructura; ese es solo otro costo

Debe ser muy agradable trabajar en Google :(. A excepción de las pocas empresas con una gran operación Go existente donde invertir en infraestructura Go es una obviedad, todos los demás tendrán que pasar por procesos de aprobación largos y tediosos. , aunque solo sea para justificar pagarle a alguien para que analice el problema, por lo que cualquier costo de infraestructura reducirá el alcance de Go y evitará su adopción por parte de nuevas estructuras.

Las empresas son como opensourcers, se preocupan por lo barato y lo fácil. Antes no les importaba en absoluto lo abierto, pero eso está cambiando lentamente ahora que se dan cuenta de que se correlaciona con lo económico (para consternación de los proveedores empresariales tradicionales que solían especializarse en costosas soluciones de caja negra con consultoría costosa para ayudar a las implementaciones).

Las empresas que contratan TI interna al mejor postor definitivamente insistirán en espejos ya que definitivamente no quieren que sus desarrolladores tacaños descarguen código roto o peligroso que esos desarrolladores no entienden de Internet. Pagarán a humanos y herramientas para escanear el contenido del espejo local en busca de problemas, y obligarán a TI interno a usarlo exclusivamente.

También queremos construir una red espejo compartida en la que los desarrolladores tengan razones para confiar, de modo que todos los desarrolladores de código abierto no sientan que deben ser proveedores.

Simplemente publique una copia de referencia de un directorio indexado que contenga módulos en alguna parte. Olvídese de cualquier configuración similar a un proxy que requiera una configuración específica del servidor web. Eso es lo que hacen los desarrolladores de código abierto y no tienen dificultad en reflejarse. Siempre que la duplicación sea simplemente copiar el contenido de un directorio y no requiera una configuración de servidor web específica, hay muchas organizaciones dispuestas a duplicar.

En cuanto al código generado de manera más general, la respuesta es un verdadero sistema de compilación multilingüe.

Sabes tan bien como yo que eso nunca sucederá, alguien siempre querrá inventar un nuevo lenguaje que haga sus propias cosas. Ese es un argumento de hombre de paja.

Eso no impide que Go normalice un comando estándar que inicie cualquier proceso específico del proyecto que genere el código, con pautas estrictas sobre lo que puede y no puede hacer (por lo general, no debería hacer nada ya cubierto por los comandos estándar de Go, porque esos comandos deberían estar ya bien como está).

específicamente porque no queremos que todos los usuarios necesiten tener instalados los generadores correctos. Es mejor que el autor ejecute los generadores y verifique el resultado.

Eso requeriría un replanteamiento importante sobre cómo se implementan los generadores existentes, porque en este momento no les importa en absoluto la portabilidad de la versión y esperan que el entorno del software se congele antes de la generación. Con el efecto directo de que generar hace que cualquier cambio de versión posterior sin regeneración sea peligroso. No importa si el resultado es verificado por humanos o no, ya que los humanos solo verificarán el conjunto de la versión original. vgo se basa en poder hacer cambios de versión posteriores.

Entonces vgo tendrá que abordar la regeneración tarde o temprano. Más tarde significa esperar a que los proyectos descubran que las actualizaciones de vgo son peligrosas en presencia del código generado.

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

Esto también afectaría cosas como los controladores de base de datos y los formatos de imagen que se registran con otro paquete durante el inicio, ya que múltiples versiones principales del mismo paquete pueden terminar haciendo esto. No me queda claro cuáles serían todas las repercusiones de eso.

Sí, el problema del código que asume que "solo habrá uno de estos en un programa" es real, y es algo en lo que todos tendremos que trabajar para establecer nuevas (mejores) mejores prácticas y convenciones. No creo que vgo esté presentando este problema, y ​​podría decirse que vgo hace que la situación sea mejor que antes.

Entiendo que algunas personas argumentan que vgo debería adoptar la regla de Dep de que ni siquiera puede haber 1.x y 2.x juntos, pero eso claramente no se adapta a las grandes bases de código a las que nos dirigimos con Go. Es inviable esperar que grandes programas completos se actualicen de una API a otra al mismo tiempo, como muestra la publicación de importación de vgo . Creo que esencialmente todos los demás administradores de paquetes permiten 1.x y 2.x juntos por la misma razón. Ciertamente Cargo lo hace.

En general, vgo reduce la duplicación en comparación con la venta. Con la venta, es fácil terminar con 1.2, 1.3 y 1.4 de un paquete dado, todo en un binario, sin darse cuenta, o tal vez incluso tres copias de 1.2. Al menos vgo reduce la posible duplicación a una 1.x, una 2.x, y así sucesivamente.

Ya es cierto que los autores de diferentes paquetes deben asegurarse de no intentar registrar lo mismo. Por ejemplo, expvar hace http.Handle("/debug/vars") y esencialmente ha reclamado ese camino. Espero que todos estemos de acuerdo en que un paquete de terceros como awesome.io/supervars no debería intentar registrar la misma ruta. Eso deja conflictos entre múltiples versiones de un solo paquete.

Si introducimos expvar/v2, terminará siendo un segundo paquete diferente, como awesome.io/supervars, y podría entrar en conflicto con expvar en una compilación grande. Sin embargo, a diferencia de supervars, expvar/v2 es propiedad de la misma persona o equipo que expvar, por lo que los dos paquetes pueden coordinarse para compartir el registro. Eso funcionaría de la siguiente manera. Supongamos que expvar v1.5.0 es el último antes de que decidamos escribir v2, por lo que v1.5.0 tiene un http.Handle en él. Queremos que v2 sea el reemplazo de v1, por lo que moveremos http.Handle a v2.0.0 y agregaremos la API en v2 que permite que v1 reenvíe sus llamadas a v2. Luego crearemos v1.6.0 que se implementa con este reenvío. v1.6.0 no llama a http.Handle; delega eso a v2.0.0. Ahora expvar v1.6.0 y expvar/v2 pueden coexistir, porque así lo planeamos. El único problema que queda es qué sucede si una compilación usa expvar v1.5.0 con expvar/v2. Tenemos que asegurarnos de que eso no suceda. Lo hacemos haciendo que expvar/v2 requiera expvar en v1.6.0 (o posterior), aunque no hay importación en esa dirección y, por supuesto, expvar v1.6.0 también requiere expvar/v2 en v2.0.0 o posterior para llamar a sus API. . Este ciclo de requisitos nos permite asegurarnos de que v1.5.0 y v2 nunca se mezclen. La planificación para este tipo de coordinación entre versiones principales es exactamente la razón por la que la selección mínima de versiones permite ciclos en el gráfico de requisitos.

La regla de "solo una versión principal" combinada con ciclos permitidos en el gráfico de requisitos brinda a los autores las herramientas que necesitan para administrar la coordinación adecuada de singletons (y la migración de la propiedad de singleton) entre diferentes versiones principales de sus módulos. No podemos eliminar el problema, pero podemos dar a los autores las herramientas que necesitan para resolverlo.

Sé que los búferes de protocolo en particular tienen problemas de registro, y esos problemas se ven exacerbados por la forma muy ad-hoc en que los archivos de protocolo .pb.go se transmiten y se copian en proyectos. Eso es nuevamente algo que es en su mayoría independiente de vgo. Deberíamos arreglarlo, pero probablemente haciendo cambios en la forma en que se usan los búferes del protocolo Go, no vgo.

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

Lo que más me preocupa es que la ruta de migración entre un mundo anterior a vgo y un mundo vgo vaya mal. [mas detalle]

Estoy muy feliz de que este haya sido el primer comentario sobre la propuesta. Claramente es lo más importante hacerlo bien.

La transición de la antigua go get y la miríada de herramientas de venta al nuevo sistema de módulos tiene que funcionar increíblemente bien. Últimamente he estado pensando mucho acerca de cómo funcionará exactamente.

La propuesta original permite a los desarrolladores la opción de poner la versión 2 de un módulo en un subdirectorio de repositorio llamado v2/. Ejercer esa opción permitiría a los desarrolladores crear un repositorio que use el control de versiones de importación semántica, sea compatible con los módulos y, sin embargo, también sea compatible con versiones anteriores del antiguo "go get". La publicación que describe esta opción admite que la gran mayoría de los proyectos no querrán ejercer esta opción, lo cual está bien. Solo es necesario para la compatibilidad si un proyecto ya está en v2 o posterior. Al mismo tiempo, subestimé la cantidad de proyectos grandes y ampliamente utilizados que se encuentran en v2 o posterior. Por ejemplo:

  • github.com/godbus/dbus está en v4.1.0 (importado por 462 paquetes).
  • github.com/coreos/etcd/clientv3 está en v3.3.3 (importado por 799 paquetes).
  • k8s.io/client-go/kubernetes está en v6.0.0 (importado por paquetes de 1928).

Para evitar romper sus clientes, esos proyectos tendrían que moverse a un subdirectorio hasta que se pueda asumir que todos los clientes usan módulos, y luego volver a la raíz. Eso es mucho pedir.

Otra opción para jugar un truco con los submódulos de git. El antiguo comando go get prefiere una etiqueta o rama llamada "go1" sobre la rama predeterminada del repositorio, por lo que un proyecto que quisiera habilitar una transición suave podría crear una confirmación en una rama "go1" que solo tenía configurado un subdirectorio "v2". como un submódulo de git que apunta hacia la raíz del repositorio real. Cuando "ir a buscar" verificó esa rama go1 y completó los submódulos, obtendría el diseño de árbol de archivos correcto. Sin embargo, eso es un poco horrible, y los punteros de los submódulos deberían actualizarse cada vez que se realiza una nueva versión.

Ambos tienen el efecto desafortunado de que los autores deben tomar medidas para evitar romper con sus usuarios, e incluso así solo para las nuevas versiones. En cambio, nos gustaría que el código de los usuarios siguiera funcionando incluso sin trabajo adicional por parte de los autores, e idealmente incluso para versiones anteriores.

Pero esas son las únicas formas en las que puedo pensar para mantener el viejo trabajo sin modificaciones a medida que hacemos la transición al mundo de los módulos. Si no es así, entonces la alternativa es modificar go get antiguo, lo que realmente significa modificar go build antiguo.

Básicamente, existen dos convenciones de ruta de importación diferentes: la antigua, sin versiones principales, y la nueva, con versiones principales en v2 o posterior. El código en un árbol antiguo probablemente usa la convención anterior, mientras que el código en un árbol nuevo, en un directorio que contiene un archivo go.mod, probablemente usa la nueva convención. Necesitamos una manera de hacer que las dos convenciones se superpongan durante una transición. Si enseñamos a los viejos a obtener una pequeña cantidad sobre el control de versiones de importación semántica, entonces podemos aumentar considerablemente la cantidad de superposición.


Cambio propuesto: defina el código "nuevo" como código con un archivo go.mod en el mismo directorio o en un directorio principal. El viejo go get debe continuar descargando el código exactamente como siempre lo ha hecho. Propongo que el paso "ir a compilar" ajuste su manejo de las importaciones en código "nuevo". Específicamente, si una importación en código nuevo dice x/y/v2/z pero x/y/v2/z no existe y x/y/go.mod dice "módulo x/y/v2", entonces go build leerá la importación como x/y/z en su lugar. Impulsaremos esta actualización como un lanzamiento puntual para Go 1.9 y Go 1.10.

Actualización : Copiado a #25069.


Ese cambio debería hacer posible que los paquetes que no conocen módulos usen versiones más nuevas de paquetes que reconocen módulos, ya sea que esos paquetes elijan el enfoque de "rama principal" o "subdirectorio principal" para estructurar sus repositorios. Ya no se verían obligados a usar el enfoque de subdirectorio, pero seguiría siendo una opción de trabajo. Y los desarrolladores que usan versiones anteriores de Go aún podrían compilar el código (al menos después de actualizar a la versión puntual).

@rsc He estado tratando de descubrir cómo podríamos hacer que la transición a vgo funcione también, llegué a las mismas conclusiones que expuso en su respuesta y su sugerencia coincide con el mejor enfoque que se me ocurrió. por mi cuenta. Me gusta tu propuesta de cambio.

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

Luego crearemos v1.6.0 que se implementa con este reenvío. v1.6.0 no llama a http.Handle; delega eso a v2.0.0. Ahora expvar v1.6.0 y expvar/v2 pueden coexistir, porque así lo planeamos.

Esto suena más fácil de lo que es. En realidad, en la mayoría de los casos, esto significa que v1.6.0 tiene que ser una reescritura completa de v1 en forma de contenedor v2 _ (la llamada reenviada a http.Handle dará como resultado el registro de otro controlador, uno de v2, que a su vez significa que todos los relacionados el código también debe ser de v2 para interactuar correctamente con el manejador registrado)_.

Es muy probable que esto cambie detalles sutiles sobre el comportamiento de v1, especialmente con el tiempo, a medida que evoluciona v2. Incluso si seremos capaces de compensar estos cambios sutiles en los detalles y emular v1 lo suficientemente bien en v1.6.x, aún así, es mucho trabajo adicional y muy probablemente haga que la rama v1 sea compatible en el futuro (me refiero a los sucesores de v1.5.0 aquí) sin sentido.

@powerman , no estoy diciendo en absoluto que esto sea trivial. Y solo necesita coordinarse en la medida en que v1 y v2 peleen por algún recurso compartido como un registro http. Pero los desarrolladores que participan en este ecosistema de paquetes deben comprender absolutamente que la v1 y la v2 de sus paquetes deberán coexistir en programas grandes. Muchos paquetes no necesitarán ningún trabajo: yaml y blackfriday, por ejemplo, están en v2 que son completamente diferentes de v1, pero no hay un estado compartido por el que pelear, por lo que no hay necesidad de una coordinación explícita, pero otros sí.

@powerman @rsc
Estoy desarrollando un paquete GUI, lo que significa que ni siquiera puedo tener más de 2 instancias debido al uso del hilo "principal". Entonces, viniendo del peor de los casos, esto es lo que he decidido hacer.

  • Solo tiene una versión v0/v1, por lo que es imposible importar más de 2 versiones

  • Tenga código público en su propia carpeta de versión de API, por ejemplo, v1/v2, suponiendo que vgo lo permita o tal vez api1/api2.

  • Esos paquetes de api públicos dependerán de un paquete interno, por lo que en lugar de tener que volver a escribir en una v2, es una reescritura continua a medida que el paquete crece y es mucho más fácil de manejar.

En https://github.com/golang/go/issues/24301#issuecomment -377529520, el cambio propuesto define el código "nuevo" como código con un archivo go.mod en el mismo directorio o en un directorio principal. ¿Esto incluye archivos go.mod "sintetizados" creados a partir de la lectura de dependencias de un Gopkg.toml, por ejemplo?

@zeebo , sí. Si tiene un archivo go.mod en su árbol, se supone que su código realmente se compila con vgo. Si no es así, ejecuta go.mod (o al menos no lo registres en tu repositorio donde otros puedan encontrarlo).

@AlexRouSg , su plan para su paquete GUI tiene sentido para mí.

@rsc hmm... No estoy seguro de haber entendido y lo siento si no estaba claro. ¿Un paquete con solo un Gopkg.toml en el árbol de archivos cuenta como "nuevo" para la definición?

@rsc

En cuanto al código generado de manera más general, la respuesta es un verdadero sistema de compilación multilingüe, específicamente porque no queremos que todos los usuarios necesiten tener instalados los generadores correctos. Es mejor que el autor ejecute los generadores y verifique el resultado.

Logramos resolver esto mapeando protobuf en GOPATH. Sí, tenemos que los usuarios ocasionales no necesitan las herramientas para actualizar, pero para aquellos que modifican y regeneran protobufs, la solución en protobuild funciona extremadamente bien.

La respuesta aquí es bastante decepcionante. Encontrar un nuevo sistema de compilación que no existe es simplemente una falta de respuesta. La realidad aquí es que no reconstruiremos estos sistemas de compilación y continuaremos usando lo que funciona, evitando la adopción del nuevo sistema vgo.

¿ vgo simplemente se declara en bancarrota para aquellos a los que les gustó y adoptaron GOPATH y solucionaron sus problemas?

@zeebo , no, tener un Gopkg.toml no cuenta como nuevo; aquí "nuevo" significa que se espera que use importaciones de estilo vgo (versiones de importación semántica).

@stevvooe :

Logramos resolver esto mapeando protobuf en GOPATH. ...
¿Vgo simplemente se declara en bancarrota para aquellos a los que les gustó y adoptaron GOPATH y solucionaron sus problemas?

No he mirado su prototipo, pero en general, sí, nos estamos moviendo a un modelo que no es GOPATH, y algunos de los trucos que GOPATH podría haber habilitado quedarán atrás. Por ejemplo, GOPATH habilitó el Godep original para simular la venta sin tener soporte de venta. Eso ya no será posible. De un vistazo rápido, parece que protobuild se basa en la suposición de que puede colocar archivos (pb.go) en otros paquetes que no son de su propiedad. Ese tipo de operación global ya no será compatible, no. Hablo completamente en serio y sincero acerca de querer asegurarme de que los protobufs estén bien soportados, separados de vgo. @neild probablemente estaría interesado en escuchar sugerencias, pero tal vez no sobre este tema.

@stevvooe dado los comentarios de @rsc en https://github.com/golang/go/issues/24301#issuecomment -377602765 He hecho referencia cruzada a https://github.com/golang/protobuf/issues/526 por si acaso ese problema termina cubriendo el ángulo vgo . Si las cosas terminan siendo tratadas en otro lugar, estoy seguro de que @dsnet et al nos indicarán.

Nota: no vi los comentarios anteriores de cerca, parece que el problema se resolvió con un enfoque diferente. Abajo estaba mi idea.

Solo una idea.

¿Qué tal hacer que vgo get tenga en cuenta una etiqueta específica como vgo-v1-lock?
Cuando un repositorio tiene la etiqueta, puede ignorar otras etiquetas de versión y anclarse a la etiqueta.

Entonces, cuando un repositorio etiquetó v2.1.3 como la última versión,
pero también el propietario inserta la etiqueta vgo-v1-lock en el mismo compromiso que está etiquetado como v2.1.3
podría escribir go.mod

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

No debería actualizarse incluso si vgo get -u , hasta que el propietario del repositorio cambie o elimine la etiqueta.
Podría facilitar la preparación de la mudanza de los repositorios grandes.

Cuando se prepara un autor de la biblioteca, el autor podría anunciar al usuario
que podrían actualizar manualmente poniendo "/v2" en su ruta de importación.

¿Cómo manejamos el caso en el que es necesario parchear una dependencia profunda (por ejemplo, para aplicar una corrección de CVE que el autor original aún no ha publicado en una etiqueta)? Parece que la estrategia del proveedor podría manejar esto, ya que podría aplicar un parche a la versión original de los autores. No veo cómo vgo puede manejar esto.

@chirino puede usar la directiva de reemplazo en el archivo go.mod para señalar el paquete parcheado.

@rsc

De un vistazo rápido, parece que protobuild se basa en la suposición de que puede colocar archivos (pb.go) en otros paquetes que no son de su propiedad.

Esto no es, en absoluto, lo que hace el proyecto. Crea una ruta de importación desde GOPATH y el directorio del proveedor. Cualquier archivo protobuf en su proyecto se generará con esa ruta de importación. También hace cosas como importar mapas a paquetes específicos de Go.

El beneficio de esto es que permite generar protobufs en un proyecto hoja que dependen de otros protobufs definidos en dependencias sin regenerar todo. GOPATH se convierte efectivamente en las rutas de importación para los archivos protobuf.

El gran problema con esta propuesta es que perdemos por completo la capacidad de resolver archivos en proyectos en relación con los paquetes Go en el sistema de archivos. La mayoría de los sistemas de empaque tienen la capacidad de hacer esto, aunque lo hacen difícil. GOPATH es único porque es muy fácil hacer esto.

@stevvooe Lo siento, pero supongo que todavía estoy confundido acerca de lo que hace protobuild. ¿Puede presentar un nuevo problema "x/vgo: no compatible con protobuild" y dar un ejemplo sencillo de un árbol de archivos que existe hoy, qué protobuild agrega al árbol y por qué eso no funciona con vgo? Gracias.

¿Qué pasa si el nombre del módulo tiene que cambiar (dominio perdido, cambio de propiedad, disputa de marca registrada, etc.)?

@jimmyfrasche

Como usuario:
Luego, como solución temporal, puede editar el archivo go.mod para reemplazar el módulo antiguo por uno nuevo manteniendo las mismas rutas de importación. https://research.swtch.com/vgo-tour

Pero a largo plazo, querrá cambiar todas las rutas de importación y editar el archivo go.mod para usar el nuevo módulo. Básicamente lo mismo que tendrías que hacer con o sin vgo.

Como mantenedor del paquete:
Simplemente actualice el archivo go.mod para cambiar la ruta de importación del módulo e informe a sus usuarios del cambio.

@jimmyfrasche ,

¿Qué pasa si el nombre del módulo tiene que cambiar (dominio perdido, cambio de propiedad, disputa de marca registrada, etc.)?

Estos son problemas reales y preexistentes que la propuesta de vgo no intenta abordar directamente, pero claramente deberíamos abordarlos eventualmente. La respuesta a la desaparición del código es tener proxies de almacenamiento en caché (espejos) junto con una razón para confiar en ellos; eso es trabajo futuro. La respuesta al movimiento de código es agregar un concepto explícito de redirecciones de módulos o paquetes, al igual que los alias de tipo son redirecciones de tipo; eso también es trabajo futuro.

La respuesta a la desaparición del código es tener proxies de almacenamiento en caché (espejos)

En mi opinión, eso realmente es para las empresas. La mayoría de las pequeñas empresas y otras estarían perfectamente bien con la venta y el compromiso de todas las dependencias en el mismo repositorio.

Archivado #24916 para la compatibilidad que mencioné en el comentario anterior.
También presentó el #24915 proponiendo volver a usar git, etc. directamente en lugar de insistir en el acceso HTTPS. Parece claro que las configuraciones de hospedaje de código aún no están listas para solo API.

propuesta menor para crear coherencia en los archivos mod con el comando vgo get planeado

En el documento "vgo-tour", el comando vgo get se muestra como:

vgo get rsc.io/[email protected]

¿Qué tal reflejar este formato en el archivo mod? Por ejemplo:

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

podría ser simplemente:

module "github.com/you/hello"
require (
    "golang.org/x/[email protected]"
    "rsc.io/[email protected]"
)
  • mejora la coherencia con la línea de comandos
  • el identificador único define el elemento por completo
  • mejor estructura para admitir operaciones definidas en el archivo mod que requieren múltiples identificadores de paquetes con versiones

Buscando más claridad sobre cómo esta propuesta trata la distribución de paquetes "solo binarios".

El control de versiones/distribución de la biblioteca binaria no parece aparecer en ninguno de los documentos de descripción de vgo. ¿Hay una necesidad de mirar esto más cuidadosamente?

De la forma en que funciona hoy, si puedo usar la herramienta simple git , go get funcionará bien. No importa si es un repositorio Github privado o mi propio servidor Git. Me encanta de verdad.

Según tengo entendido, va a ser imposible seguir trabajando así. ¿Es eso cierto? En caso afirmativo, ¿es posible mantener la opción de usar un binario git instalado localmente para verificar el código? (en caso de que esté usando un indicador CLI explícito)

@korya Consulte el problema presentado recientemente https://github.com/golang/go/issues/24915

@sdwarwick , re https://github.com/golang/go/issues/24301#issuecomment -382791513 (sintaxis go.mod), consulte #24119.

re https://github.com/golang/go/issues/24301#issuecomment -382793364, es posible que no entienda lo que quiere decir, pero go get nunca admitió paquetes solo binarios, y no estamos planeando para agregar soporte. Es demasiado difícil enumerar todos los diferentes binarios posibles que uno podría necesitar. Es mejor requerir la fuente y poder volver a compilar cuando cambien las dependencias o el compilador.

@rsc Creo que https://github.com/golang/go/issues/24301#issuecomment -382793364 se refiere a
https://golang.org/pkg/go/build/#hdr -Binary_Only_Packages

@AlexRouSg Sí. Esos no son compatibles con "ir a buscar" (pero "ir a compilar" los admite como un tipo de compilación), que es a lo que se refiere @rsc . La distribución de esos tipos de paquetes debe realizarse externamente a las herramientas de "ir a buscar" y, por lo tanto, probablemente sea lo mismo para esta nueva propuesta.

Espero que el soporte actual para paquetes solo binarios continúe funcionando tan mal como siempre. No saldré de mi camino para quitarlo.

Actualicé el resumen de la discusión nuevamente. También presenté el n.º 25069 por mi sugerencia anterior sobre el reconocimiento mínimo de módulos en el antiguo cmd/go.

@kybin , re https://github.com/golang/go/issues/24301#issuecomment -377662150 y la etiqueta vgo-v1-lock , veo el atractivo, pero agregar un caso especial significa agregar más casos especiales en todo el resto del soporte del módulo. No creo que el beneficio sea proporcional al costo en este caso. La gente ya puede usar pseudo-versiones para obtener un efecto similar. También me preocupa que la etiqueta se mueva y/o las personas no respeten correctamente la compatibilidad con versiones anteriores (por ejemplo, mover vgo1-v1-lock de v2.3.4 a v3.0.0 solo para evitar el control de versiones de importación semántica). Entonces, en balance, creo que probablemente no deberíamos hacer esto.

Creo que es hora de marcar esta propuesta aceptada.

Nunca hubo suspenso sobre si sería aceptado de alguna forma. En cambio, el objetivo de la discusión aquí fue determinar la forma exacta, para identificar lo que debemos ajustar. Como escribí en la entrada del blog :

Sé que hay problemas que el equipo de Go y yo no podemos ver, porque los desarrolladores de Go usan Go de muchas maneras inteligentes que no conocemos. El objetivo del proceso de comentarios de la propuesta es que todos trabajemos juntos para identificar y abordar los problemas de la propuesta actual, para asegurarnos de que la implementación final que se envíe en una futura versión de Go funcione bien para tantos desarrolladores como sea posible. Señale los problemas en el tema de discusión de la propuesta. Mantendré actualizado el resumen de la discusión y las preguntas frecuentes a medida que lleguen los comentarios.

El resumen de la discusión y las preguntas frecuentes están actualizados en este momento. La discusión aquí y fuera del tema provocó los siguientes cambios importantes:

  • conocimiento mínimo del módulo en cmd/go antiguo, #25069.
  • restaurando el soporte mínimo del proveedor, #25073.
  • restaurando el soporte para el acceso directo a Git, #24915.
  • suelte las comillas en go.mod, #24641.
  • mejor soporte para gopkg.in, #24099, otros.
  • soporte para nombrar compromisos por identificadores de rama, #24045.

También provocó discusiones sobre la posibilidad de cambiar el nombre y la sintaxis del archivo go.mod, pero el único cambio resultante fue eliminar las comillas.

La discusión se ha calmado, y también se ha hecho lo suficientemente larga como para que sea bastante doloroso cargarla en GitHub (¡aparentemente 100 comentarios son demasiados!). Al marcar la propuesta como aceptada, podemos centrarnos en usar vgo y prepararlo para su inclusión en Go 1.11 como una "vista previa", y podemos pasar a problemas que GitHub puede cargar más rápidamente.

Hay, por supuesto, aún más errores por encontrar y corregir, y más ajustes de diseño por hacer. Las discusiones de esos detalles se pueden hacer sobre nuevos temas específicos a esos detalles. Utilice un prefijo "x/vgo:" y el hito vgo .

Gracias a todos.

@rsc ¿Cuál es la forma de probar vgo ahora? ¿Deberíamos obtener y compilar github.com/golang/vgo o github.com/golang/go?

@ngrilly sigue usando go get -u golang.org/x/vgo .

@rsc , gracias por el arduo trabajo y el tiempo que ha dedicado a esta propuesta. Realmente espero que finalmente lleguemos a un punto en el que haya una buena historia sobre la administración de dependencias de Go.

Creo que es hora de marcar esta propuesta aceptada.

No creo que sea apropiado que una persona que presente una propuesta declare cuándo está lista para ser aceptada. Creo que aquellos que presentan una propuesta, especialmente una tan grande y obstinada, no deberían opinar sobre su aceptación. Su presentación de la propuesta comunica sus sesgos. Por otro lado, creo que los autores definitivamente deberían tener voz para rechazar la propuesta si cambian de opinión después de plantearla.

En este momento parece que hay profundos desacuerdos en torno a las decisiones técnicas dentro vgo , que me temo que fragmentarán el ecosistema _y_ la comunidad. Con eso en mente, creo que deberíamos dar un poco más de tiempo para que las propuestas en competencia estén terminadas y sean el centro de atención. Una vez que eso suceda, necesitamos tener una parte _neutral_ que consista en la representación de varias empresas y la comunidad, para facilitar la discusión y la decisión final.

Me preocupa cada vez más que una buena parte del liderazgo de Go se haya aislado demasiado de la comunidad detrás de Go (incluidas otras empresas que lo usan) y que, como resultado, el lenguaje y el ecosistema comiencen a doler. Es por eso que creo que necesitamos tener un grupo neutral, con una representación que refleje a los usuarios del lenguaje de programación Go, ayudar a ratificar propuestas como esta.

En última instancia, trabajar como ingeniero de software dentro de Google da como resultado una perspectiva diferente en comparación con una gran parte de la industria. Tener la masa crítica de los desarrolladores principales dentro de Google no contribuye a la diversidad que necesitamos cuando impulsamos el avance.

@theckman Su línea de pensamiento parece ser:

  1. Las decisiones sobre Go las toma un pequeño equipo compuesto principalmente por ingenieros de Google.
  2. Los ingenieros de Google están aislados del resto de la comunidad porque las necesidades de Google son muy específicas.
  3. Esto conduce a decisiones que favorecen la perspectiva de Google y no se adaptan a otros usuarios de Go.
  4. Esto podría dañar y fragmentar a la comunidad de Go.
  5. Para resolver este problema, Go debe adoptar un proceso de decisión formal en el que las decisiones se tomen de manera colegiada por un grupo que refleje la diversidad de la comunidad Go (algo "democrático").

En teoría, me inclinaría por algo "democrático", pero en la práctica:

  • No creo que las decisiones tomadas por el equipo de Go estén sesgadas hacia las necesidades de Google, a expensas de los "pequeños" usuarios de Go. Como desarrollador en una tienda muy pequeña (todo lo contrario a Google), siento que Go se adapta muy bien a nuestras necesidades, y conozco otros equipos pequeños a mi alrededor que usan Go felizmente. Personalmente, las únicas quejas que tengo con el lenguaje Go han sido reconocidas por el equipo Go (administración de dependencias, falta de genéricos, manejo detallado de errores) y confío en que están trabajando en ello. ¿Podría proporcionar ejemplos de decisiones tomadas por el equipo de Go que habrían sido diferentes y habrían servido mejor al "resto de la comunidad" si tuviéramos un proceso "democrático"?

  • No estoy convencido de que la adopción de un proceso de decisión "democrático" resuelva automáticamente los problemas que mencionó y elimine el riesgo de "fragmentar" la comunidad. Puede ser una mejora sobre el modelo BDFL , pero no es una garantía de estabilidad per se. La historia de código abierto, y la historia humana en general, proporciona muchos ejemplos de sociedades democráticas que han sido arruinadas por desacuerdos y conflictos.

@theckman , mientras que @ngrilly estaba tratando de ser cortés, seré concreto: si ve algún problema técnico por el cual la propuesta de vgo no está lista para ser aceptada, ¡díganos lo antes posible y aquí mismo! Si cree que algunos problemas conocidos no se abordaron adecuadamente, infórmenos. Si no hay tales casos, ¿cuál es la diferencia en quién dirá "es hora de aceptar la propuesta"? Tuvimos dos meses para discutirlo, si cree que hay una razón técnica por la que no es suficiente, díganoslo.

Parece que quieres agregar más política aquí sin motivo, lo que solo ralentizará todo, y eso es si tenemos la suerte y no hace ningún otro daño. E incluso si cree que hay una razón para esto, este no es el lugar adecuado para discutir esto, inicie esta discusión en la lista de correo.

¡Perdón por un comentario más fuera de tema, todos!

@powerman Perdón por ser tonto y citar mi comentario anterior:

En este momento, parece que hay profundos desacuerdos en torno a las decisiones técnicas dentro de vgo, que me temo que fragmentarán el ecosistema y la comunidad. Con eso en mente, creo que deberíamos dar un poco más de tiempo para que las propuestas en competencia estén terminadas y sean el centro de atención.

Sé que se avecinan propuestas alternativas, y mi pedido fue descartar la aceptación de esto hasta que tengan la hora del día. Hace tiempo que no tenemos gestión de dependencias, así que creo que no es descabellado pedir una estancia corta mientras se dan los toques finales a otras propuestas.

No estoy seguro de que sea fácil articularlo bien en este número, solo porque el formato es un poco limitado. Incluso entonces dudaría, porque básicamente estaría duplicando partes de las propuestas WIP. No me gustaría fragmentar las ideas o robarle el protagonismo a los autores.

Sin embargo, sabiendo que esas propuestas están en progreso y quién está trabajando en ellas, sentí que la declaración de que esto estaba listo fue un intento activo de sofocar esas opiniones en competencia. Me sentí obligado a plantear estas preocupaciones debido a los patrones que he observado durante mis años como Gopher. Realmente quiero que el idioma, el ecosistema y la comunidad tengan éxito, y estos se plantean únicamente con ese objetivo en mente.

Editar: Para aclarar, por estadía corta no me refiero a dos meses ni nada de eso. Me refiero a unas pocas semanas.

@ngrilly Lo siento, no quise ignorar tu comentario. Planeé dirigirlo al anterior, pero terminé siendo más detallado de lo que quería.

Creo que hay dos problemas. Si bien creo que hay algo que debatir en un foro diferente sobre cómo se toman estas decisiones, razón por la cual agregué algo de contexto al respecto, realmente quiero centrarme en poner una pausa temporal en la aceptación de esta propuesta hasta que esas otras propuestas hayan terminado. tuvo la oportunidad de hacerse público.

Sé que se avecinan propuestas alternativas, y mi pedido fue descartar la aceptación de esto hasta que tengan la hora del día. ... [S]abiendo que esas propuestas están en progreso y quién está trabajando en ellas, sentí que la declaración de que esto estaba listo fue un intento activo de sofocar esas opiniones en competencia.

Te aseguro que no fue así. He sido bastante claro acerca de la línea de tiempo aquí. Mi primera publicación de mediados de febrero dice que el objetivo es integrar la propuesta de vgo en Go 1.11; se acerca la congelación del desarrollo. No sé nada sobre otras propuestas en curso o quién está trabajando en ellas. Eso es nuevo para mí. Si la gente quiere comprometerse con esta propuesta o hacer contrapropuestas, esta propuesta ha estado abierta durante un mes y medio, por lo que se está haciendo un poco tarde.

Para ser claros, no marqué la propuesta como aceptada, a pesar de lo que informó Golang Weekly y tal vez otros. Solo dije que creo que es hora de hacerlo. Es decir, no apliqué la etiqueta de Propuesta Aceptada, precisamente porque quería comprobar primero que había un consenso general para hacerlo. Y el consenso general parece estar a favor de la aceptación, al menos a juzgar por la discusión general aquí, así como los contadores de emoji en https://github.com/golang/go/issues/24301#issuecomment -384349642.

Sé que vienen propuestas alternativas

@theckman , si sabe algo como esto, probablemente sea el único que lo sepa. Hasta la fecha, no he visto a nadie planteando este problema hasta ahora. Creo que las declaraciones de Russ sobre querer probar esto para Go 1.11 fueron muy claras desde el principio, por lo que si alguien está trabajando en propuestas alternativas, tuvo alrededor de 2 meses para presentarlas, incluso como aviso.

También creo que podemos aceptar el hecho de que el Go Team tiene un buen historial de no tomar decisiones por capricho, y si nos fijamos solo en cómo sacaron el Alias ​​en el último momento de Go 1.8 ya que no era el correcto. qué hacer en ese momento, entonces probablemente deberíamos darles la cortesía de al menos permitirles construir su propio experimento/solución.

Al final del día, la propuesta trae mucho más que un algoritmo sobre cómo seleccionar qué versión de la dependencia se usa. Si alguien encuentra una manera de mejorarlo, entonces hay dos opciones: enviarlo a través del proceso CL regular O crear su propia herramienta y dejar que la comunidad la use, si así lo desea. El Go Team aún puede proporcionar su propia versión de la herramienta, en mi humilde opinión, por lo que no veo que esto tenga un problema cerrado.

Sin embargo, tenga en cuenta que la mayoría de las acciones divisivas fueron tomadas hasta ahora por la comunidad, no por el Go Team. Démosle al equipo Go la oportunidad de crear una herramienta y luego evaluarla, cuando sea viable hacerlo, luego presentar argumentos sobre cómo mejorarla y avanzar en lugar de escribir sobre lo malo que es.

Considere esto como parte de un tipo diferente de informe de experiencia: aquel en el que yo era un opositor _muy_ vocal de la propuesta de Alias ​​para luego comprender y ahora ver la propuesta en acción.

Editar: el mensaje original tenía una omisión muy desafortunada record of *not* making decisions on a whim debería haber sido el texto, desafortunadamente faltaba la parte "no". Mis disculpas por ello.

tengo una descripción detallada de las preocupaciones fundamentales con la propuesta. He estado tratando de terminar este artículo para poder presentarlos todos a la vez; este es un dominio complejo y sutil y, como tal, estos problemas deben abordarse en su totalidad, pero la vida y el trabajo lo han dificultado.

Si bien he aludido a este artículo en Slack, así como discutido partes del mismo directamente con @rsc , he optado por no mencionarlos aquí hasta ahora. Me pareció que anunciar este artículo antes de estar preparado para publicarlo por completo no sería muy constructivo. Pero, como se ha señalado, han pasado dos meses, así que voy a hacer un gran esfuerzo para que la serie comience la próxima semana.

(editar: estas son las "alternativas" a las que se refería @theckman )

@sdboyer Mencionaste que tienes múltiples preocupaciones. ¿Podrías al menos publicar su lista ahora mismo?
Estoy trabajando con varios sistemas que llevan el infierno de las dependencias a otro nivel (chef, go, npm, composer) y por experiencia esta propuesta es la solución para todos ellos en lo que respecta a go.

@theckman , ¿puede confirmar que solo se refería a los comentarios de @sdboyer ? Eso no es un secreto. Sam lo mencionó literalmente el primer día que se lanzó vgo ("Estoy escribiendo documentos más detallados sobre mis preocupaciones" - https://sdboyer.io/blog/vgo-and-dep/). Pero eso es retroalimentación, no una propuesta, y usted se refirió varias veces a "otras propuestas", en plural. ¿Hay algo más que sepas?

¿Cuáles son las implicaciones de vgo para los usuarios de la API go/types? ¿Cuál es el estado actual del soporte de go/types?

Recibí un PR mdempsky/gocode#26 para agregar una implementación de vgo-aware go/types.Importer, pero no tengo claro si/por qué esto es necesario.

Suponiendo que sea necesario, ¿podemos agregar un go/types.Importer canónico compatible con vgo en otro lugar (por ejemplo, el repositorio x/vgo o x/tools) para que las herramientas basadas en go/types no necesiten volver a implementar este soporte cada una? ?

Realmente no he seguido los detalles de vgo, así que tal vez esto sea simplemente "sin impacto", pero no veo ninguna mención de go/types arriba. Las búsquedas en Google de "vgo go/types golang" tampoco son informativas.

Gracias.

@mdempsky , el plan es tener un cargador de paquetes con reconocimiento de vgo (y para el caso, compilar con reconocimiento de caché), probablemente golang.org/x/tools/go/packages, pero aún no existe. La gente debería esperar ese paquete en lugar de escribir código que deberá desecharse. No fusiones las relaciones públicas. Lo comenté.

@mdempsky iba a responder en https://github.com/mdempsky/gocode/pull/26 pero responderé aquí por ahora.

https://github.com/mdempsky/gocode/pull/26 es completamente desechable; solo una prueba de concepto que usa un CL ahora abandonado contra vgo .

Acabo de ver la respuesta de @rsc , así que simplemente señalaré que también hay una discusión en https://github.com/golang/go/issues/14120#issuecomment -383994980.

Resumen: después de algunos años de experiencia con versiones, el último mejor intento fue un algoritmo muy complejo, un solucionador sat. Pero si realiza algunas modificaciones simples a los datos de entrada, el problema de decisión NP-completo se convierte en algo no solo manejable, sino muy rápido.

Como usuario de un equipo pequeño de Go con mucha experiencia en el uso de NPM, me gusta mucho la propuesta de vgo. FWIW, espero que vgo se implemente en go correctamente y cuanto antes llegue, mejor para mi equipo y para mí.

No es que sea alguien especial, solo que desde que vi una discusión sobre los problemas de los equipos pequeños, pensé en intervenir.

Aquí está mi reseña.

En la superficie, la sección _Propuesta_ de la última revisión del documento de la propuesta parece estar bien, aunque no es muy específica (por ejemplo, no está claro hasta qué punto se admite Subversion ). Una excepción es que "No permitir el uso de directorios de proveedores, excepto en un uso limitado" parece decir que los directorios de proveedores no serán compatibles en absoluto en paquetes que no sean módulos; ¿Es eso así?

Por otro lado, la propuesta implica ciertas decisiones de diseño e implementación que socavan varios beneficios del actual go get . Las pérdidas pueden ser aceptables, algunas pueden evitarse, pero si vgo get va a reemplazar go get , deben abordarse como consideraciones de diseño y discutirse, porque de lo contrario podemos terminar con una herramienta que es no es un reemplazo adecuado, y vgo no se fusionará con go o go get tendrá que resucitar como una herramienta de terceros.

La sección _Implementación_ dice: “En una versión posterior (digamos, Go 1.13), finalizaremos el soporte para go get de no módulos. El apoyo para trabajar en GOPATH continuará indefinidamente”. Esto es problemático. Primero, hay muchos buenos proyectos que no se han actualizado en años. Todavía funcionan gracias a la promesa de compatibilidad con Go 1, pero muchos no agregarán archivos go.mod . En segundo lugar, obliga a los desarrolladores de proyectos sin dependencias oa los que no les importan las versiones a añadir archivos de módulos o abstenerse del nuevo ecosistema go get . Puede estar justificado para querer esto, pero explique por qué. (A mí me parece innecesariamente engorroso; prefiero usar la bifurcación del antiguo go get . Acepto que los gestores de paquetes para otros lenguajes son aún más engorrosos, y estoy seguro de que vgo es mejor que ellos, pero no maneja mis casos de uso mejor que el go get actual, con la ayuda ocasional de govendor ).

Mi principal preocupación sobre vgo vs go es el flujo de trabajo que admiten. Lo había expresado en la publicación vgo-intro. En términos generales, esto podría pertenecer a la sección _Compatibilidad_ de la propuesta, o podría estar fuera de su alcance, pero se corresponde con otras preguntas y cuestiones planteadas aquí.

Como referencia, aquí hay una copia de mi comentario de introducción de vgo.

En una versión posterior, eliminaremos la compatibilidad con el antiguo Go Get no versionado.

Si bien otros aspectos de la propuesta suenan bien, este es desafortunado. (Tanto que si tuviera que elegir entre incorporar el control de versiones en la cadena de herramientas de go y seguir trabajando con las herramientas de control de versiones, elegiría lo último). La ventaja de vgo es que facilita las compilaciones reproducibles y retrasa la interrupción de su proyecto. por actualizaciones incompatibles hasta que tú como autor del proyecto (con el archivo go.mod) quieras afrontarlo; pero la ventaja de ir a buscar es que trae los beneficios de un monorepositorio al mundo de los múltiples repositorios: debido a los clones completos de las dependencias, puede trabajar con ellas tan fácilmente como con su propio proyecto (inspeccionar historial, editar, diferenciar cambios; ir a la definición de cualquier cosa y echarle la culpa), facilita la colaboración (usted simplemente empuja y propone sus cambios) y generalmente impone la visión de que en cualquier momento solo hay un estado actual del mundo, la punta de cada proyecto, y todo lo demás es historia. Creo que este enfoque único (fuera de los monorepos reales) es una ventaja distintiva del ecosistema Go que hizo más bien que mal, y no debe abandonarse.

Una consecuencia negativa más sutil de la propuesta es que hace que el control de versiones sea incurable y heredable: una vez que un proyecto etiqueta una versión, no puede esperar que los cambios futuros lleguen a los usuarios sin etiquetar nuevas versiones. Incluso si el autor original sigue decidido a seguir etiquetando, los autores de las bifurcaciones ahora se ven obligados a etiquetarlos también (lo que es particularmente incómodo si el proyecto de origen todavía está activo) o a eliminar las etiquetas antiguas.

En general, quiero enfatizar que el enfoque actual de Go para la administración de dependencias es en general superior al control de versiones. Se alinea mejor con el código abierto moderno, dinámico y colaborativo que espera que todos los compromisos sean visibles, y publicar solo las fuentes de los lanzamientos (o "integrar cambios internos" en compromisos no descriptivos enormes) no es suficiente (porque reduce severamente la visibilidad, la colaboración y dinamismo). Se puede ver tanto en monorepos como en el ecosistema Go actual que la mayoría de los proyectos no necesitan versiones. Por supuesto, este enfoque no es el último, tiene desventajas y es importante admitir proyectos con versiones también, pero esto no debe hacerse en detrimento de los que no tienen versión.

Para resumir, el go get actual (con herramientas auxiliares, por ejemplo, godef ) admite el flujo de trabajo que incluye:

  • código fuente editable de las dependencias
  • código fuente de las dependencias bajo su VCS
  • últimas revisiones de las dependencias

Supongo que puedo suponer que el código fuente de las dependencias seguirá siendo editable, es decir, godef se vinculará a _archivos_ que _no están protegidos contra escritura_ y _utilizados durante la compilación_. Sin embargo, vgo va a incumplir los otros dos puntos. Con respecto al segundo punto, #24915 ha prolongado el soporte para herramientas VCS, pero aún declara el objetivo de eliminarlo; y el flujo de trabajo requiere no solo que las dependencias se desprotejan de VCS, sino también que el pago sea útil para los desarrolladores (por ejemplo, no es un pago de git superficial, no es un pago de git con .git eliminado) y se usa durante la compilación , pero es posible que vgo no cumpla este requisito. Con respecto al tercer punto, he justificado su valor en el comentario de vgo-intro, pero vgo parece estar abandonándolo por completo.

Una herramienta de control de versiones de Go no tiene que dejar de admitir el flujo de trabajo actual, y no debe dejarlo para mantener los beneficios únicos de trabajar en el ecosistema de Go y ser un reemplazo adecuado para go get . El diseño de vgo hace que esto sea desafiante, pero obviamente no inviable. La sección _Propuesta_ de la propuesta, por otro lado, parece casi compatible con el flujo de trabajo actual. El único desafío que presenta para respaldar el tercer punto (comprobar la última revisión), y es importante, es que dificulta decidir si los módulos ≥v2.0.0 se pueden verificar en master , o si deben verificarse como se especifica porque master está en otra versión principal. Esto no es un desafío para el go get actual con gopkg.in porque todo está desprotegido en master de manera predeterminada, y las cosas en gopkg.in están desprotegidas en la etiqueta o rama correspondiente; pero vgo difumina esta distinción y extiende el modelo gopkg.in a todos los paquetes. (Además, deja de hacer coincidir las ramas). En efecto, se vuelve imposible saberlo con certeza y es necesario adivinar cómo obtener la última revisión de la versión principal especificada.

Puede que me lo haya perdido, pero ¿cómo funcionaría vgo en este escenario?

  • Trabajo en el servicio A y el servicio B, ambos dependiendo de lib X (en el que también trabajo)
  • Necesito un cambio importante en lib X

Con las formas actuales de hacerlo, solo hago mis cambios, compilo el servicio A y el servicio B, ellos toman lo que sea que esté en mi $GOPATH para lib X, arreglo cosas, luego presiono lib X con un gran impulso, luego presiono ambos servicios A y B diciéndoles que usen la nueva especialidad de lib X en su Gopkg.toml .

Ahora, cuando vgo se haga cargo, go build en mis servicios intentará encontrar una nueva versión no existente de lib X de github, y puedo prever todo tipo de problemas.

Entonces, ¿me estoy perdiendo algo obvio?

Puede usar la directiva replace para este tipo de cosas.

El lunes 30 de abril de 2018 a las 12:15 Antoine [email protected] escribió:

Puede que me lo haya perdido, pero ¿cómo funcionaría vgo en este escenario?

  • Trabajo en el servicio A y el servicio B, ambos dependiendo de lib X (que
    también trabajar en)
  • Necesito un cambio importante en lib X

Con las formas actuales de hacer, solo hago mis cambios, compilo el servicio A y
servicio B, recogen lo que sea que esté en mi $GOPATH para lib X, arreglo cosas,
luego presiono lib X con un gran golpe de semver, luego presiono ambos servicios A y B
diciéndoles que usen la nueva versión principal de lib X en su Gopkg.toml.

Ahora, cuando vgo se haga cargo, vaya a construir en mis servicios intentará encontrar no
nueva versión existente de lib X de github, y puedo prever todo tipo de
nubes.

Entonces, ¿me estoy perdiendo algo obvio?


Estás recibiendo esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/golang/go/issues/24301#issuecomment-385499702 , o silenciar
la amenaza
https://github.com/notifications/unsubscribe-auth/AAuFsfnD8_kbUj8fSXvGgeN77ki6KYM6ks5tt2LLgaJpZM4Sg3bp
.

@kardianos , sí, ¿pero eso todavía significa que tengo que presionar mis cambios de lib para intentarlo?

EDITAR: parece que puede usar rutas para reemplazar (https://github.com/golang/go/issues/24110), lo cual es bueno. Pero también puedo predecir que esto acabará cometiéndose muchas veces.

¿Algún plan para poder crear un archivo adicional, como go.mod.replace o algo así, para que podamos definir las anulaciones en entornos de desarrollo y gitignorarlas?

@primalmotion Para evitar malas confirmaciones, probablemente debería usar un git hook.

Pero supongo que la respuesta correcta es simplemente no hacer esto (reemplazar a la ruta local) con demasiada frecuencia. Si su biblioteca está tan estrechamente acoplada, entonces no debería vivir en un repositorio separado (y, por lo tanto, fingir que está débilmente acoplada). En general, debería poder reparar, probar y liberar esa librería sin tener en cuenta la implementación actual de estos servicios. Especialmente con vgo, que garantiza que ambos servicios continuarán usando la versión anterior de lib (que estaban usando antes) hasta que los actualice manualmente a la versión más nueva de esa lib. Si ocasionalmente se compromete a reemplazar las rutas locales una vez al año, no es gran cosa, CI lo ayudará a notarlo y solucionarlo en unos minutos.

@primalmotion con un go.mod.replace no versionado, puede enviar un proyecto que no será reproducible. En cambio, con replace en go.mod está seguro de que confirma exactamente lo que usa y prueba actualmente.
Puede ser un error cometer un reemplazo, pero lo notará y lo corregirá.
O puede ser voluntario, lo hago con submódulos, está bien cuando trabajas en un proyecto y una biblioteca juntos y es reproducible si confirmas el submódulo. Lo hice a menudo en Python y me lo perdí con Go. Con vgo estoy feliz de poder volver a trabajar así. _(espero ser claro con mi mal inglés, lo siento)._

Bueno, el problema es que no nos importan las compilaciones reproducibles hasta que decidimos que nos importan (es decir, cuando preparamos los lanzamientos). Tenemos un entorno de desarrollo muy ágil en el que actualizar una lib es solo pagar, reconstruir y ejecutar pruebas. No comprometemos el Gopkg.lock en las ramas maestras de nuestros servicios, solo el toml con versiones fijas para bibliotecas externas y restricciones importantes en el nuestro. Una vez que creamos una rama de lanzamiento, confirmamos el Gopkg.lock y solo entonces tenemos compilaciones reproducibles (esto lo hace nuestro ci).

Vgo básicamente rompe todos los flujos de trabajo que hemos creado a lo largo de los años. Ahora, solo para probar algo tan tonto como una pequeña depuración de impresión en una biblioteca (porque todos hacemos esto, no mientas :)), o una pequeña optimización, tendremos que revisar docenas de servicios, agregar replace directivas en todas partes, pruebe, luego regrese y elimínelas todas.

Lo que podría hacer que vgo funcione para nosotros:

  • un sistema de anulación como mencioné
  • una forma de no usarlo en absoluto y recurrir al viejo GOPATH para el desarrollo.

Y realmente queremos que funcione para nosotros, porque es increíble.

¿Podemos tener algo para probar en go 1.11 (ahora está congelado) o tal vez en go 1.12?
Ya está marcado como experimental. Y creo que cuantas más personas lo prueben en desarrollo real, más valiosos serán los comentarios.

Leí sobre el problema relacionado con los paquetes versionados. Para un escenario simple, si escribo una biblioteca que dice usar un dep para analizar plist llamado foo-plist . Como consecuencia del análisis, esa biblioteca plist expone ciertos tipos propios. Ahora esa biblioteca se actualiza a v2, y mi biblioteca se ve obligada a actualizarse a v2 si devolviera algún objeto de esos tipos de plist.

Esto parece bastante difícil de resolver, por ejemplo, si deseo que mi biblioteca sea compatible con v1 y v2 de dicha biblioteca plist bajo la impresión de esta propuesta.

Bajo npm, por ejemplo, mi biblioteca puede simplemente especificar una dependencia de pares para decir >=1.0.0|>=2.0.0 y depende del usuario de mi biblioteca decidir qué versión de plist usar. Entonces, si el usuario de mi biblioteca foo-plist también usa otra biblioteca que depende de plist , entonces si ambas bibliotecas están satisfechas con v1 y v2 de plist, entonces el usuario puede elegir cuáles en realidad importar. Más importante aún, si ambas bibliotecas exportan tipos de plist, esos tipos serán realmente compatibles.

Si terminan siendo diferentes rutas de importación, no creo que haya ninguna forma de admitir eso.

@itsnotvalid foo-plist.2 puede importar foo-plist y volver a exportar sus tipos usando alias de tipo. Puede encontrar una buena descripción de esta técnica aquí https://github.com/dtolnay/semver-trick

Aram señaló aquí la dificultad de retrotraer cambios a ramas (o directorios) de versiones anteriores. Debido a que las referencias "propias" a las fuentes dentro del mismo módulo también incluyen la versión en la ruta de importación, los parches no se importarán correctamente o uno puede introducir inadvertidamente importaciones de versiones cruzadas.

¿Pensamientos?

Para ser claros, me siento completamente cómodo con las importaciones de módulos cruzados usando versiones en la ruta de importación; Creo que los argumentos de Russ han sido muy convincentes. Soy menos claro acerca de ellos para las importaciones dentro del módulo. Entiendo el objetivo de tener una única ruta de importación para un paquete determinado en una compilación (independientemente de si se importa entre módulos o dentro de su propio módulo), pero si tuviera que elegir, preferiría tener una solución para problema de Aram que mantener esta propiedad. (Además, me imagino que el sistema de compilación podría inyectar la versión del archivo mod al crear un módulo de nivel superior y, literalmente, inyectarlo en la fuente después de descargar una dependencia del módulo)

@rsc , ¿hay alguna posibilidad de que esto avance? No veo nada importante que detenga esto.

Lo siento si parezco impaciente con esto, pero hay más y más herramientas trabajando en el soporte para vgo y cuanto más lo retrasemos, más complicado será para nosotros, los mantenedores de herramientas, ir y venir en esto. .

@sdboyer planea publicar sus artículos esta semana. Diría que es justo esperarlos.

Creo que el algoritmo de resolución para seleccionar qué versiones de dependencia no debería ser la causa del bloqueo de toda la propuesta, que también contiene cosas como módulos, soporte de proxy, control de versiones, etc.

Y si, más adelante, decidimos mejorar/cambiar el algoritmo para descargar estas dependencias, entonces podemos hacerlo sin afectar nada más.

Estoy de acuerdo con @dlsniper : ya estamos bien congelados y han pasado casi tres meses desde que se presentó el diseño de vgo. Si su trabajo en 1.11 se retrasa aún más, me preocupa que se retrase a 1.12.

La primera publicación de lo que será una serie finalmente está en vivo . Pido disculpas por haber tardado tanto en publicarse, y pasará aún más tiempo antes de que concluya la serie. Pero, la primera publicación proporciona una descripción general amplia de los temas que pretendo cubrir en toda la serie, por lo que la gente al menos debería poder tener una idea del alcance.

Brevemente: hay muchas cosas geniales sobre vgo, muchas de las cuales nosotros, como comunidad, hemos querido durante mucho tiempo. Sin embargo, creo que MVS no es apto para su propósito y no debería llegar a la producción. Es una pena que tantas de estas cosas que queremos se hayan incluido en MVS, especialmente cuando tan pocas de ellas son específicas. Estoy trabajando en un enfoque alternativo, al que se hace referencia con fines comparativos a lo largo de la serie del blog, y se articulará en la publicación final.

El algoritmo central alternativo en el que estoy trabajando probablemente sea bastante sencillo de migrar a go.mod , por lo que no anticipo que tengamos problemas, probablemente sería posible dejar que esto avance tal como está, si se agregó un archivo de bloqueo separado que contiene el cierre transitivo de las dependencias, y tiene _eso_ de lo que lee el compilador, en lugar del algoritmo de la lista de compilación. (También hay otras razones para un archivo de bloqueo, aunque eso estará en la publicación 5). Como mínimo, eso nos da una válvula de escape.

Sin embargo, si decimos que MVS está bien, incluso como un recurso provisional, entonces entra y gana la ventaja de la inercia. En ese punto, tenemos que demostrar que es inadecuado para @rsc (aunque en realidad, ya lo estableció como el estándar incluso antes de que se fusione), y cree que esta es una declaración verdadera sobre go get , en este momento:

Hoy en día, muchos programadores en su mayoría no prestan atención a las versiones, y todo funciona bien.

Teniendo en cuenta todo lo anterior, mi temor es que dejar que esto avance ahora creará "genéricos, ronda dos", excepto que esta vez se trata de reglas que rigen la forma en que interactuamos entre nosotros, no con las máquinas.

Sin embargo, si decimos que MVS está bien, incluso como un recurso provisional, entonces entra y gana la ventaja de la inercia.

Tenga en cuenta que, en este momento , dep tiene la ventaja de la inercia (tanto por estar construido en las mismas premisas que los administradores de versiones de otros idiomas como por existir por más tiempo con un amplio apoyo de la comunidad). Al menos para mí, la propuesta de vgo aún logró superar esta inercia al ser un buen diseño, respaldado por buenos argumentos.

Personalmente, no me importa si la versión en Go se retrasa, estoy totalmente a favor de hacer algo bien en lugar de rápido. Pero al menos por el momento, vgo todavía me parece la solución correcta (y AIUI muchas personas en la comunidad perciben esto como un problema urgente).

@mvdan Este cambio no está exento de repercusiones. Todos queremos esto, pero creo que también es aconsejable tomarse un tiempo extra para calmar las dudas, especialmente cuando la persona que plantea esas dudas claramente ha pensado mucho en el problema.

Sigo escuchando la mención de la congelación y su impacto en obtener una vista previa de vgo en 1.11 . ¿Cuál es la línea oficial en este punto sobre si esto se integrará por 1.11 ? Este problema me parece sorprendentemente silencioso considerando el impacto potencial.

@sdboyer , ¿cuál es su posición sobre si esto debería fusionarse con 1.11 teniendo en cuenta que solo _acaba_ de declarar oficialmente, públicamente, su posición en MVS?

Si esto no llega a 1.11 , entonces no tendremos esto oficialmente disponible para vista previa hasta 1.12 en febrero de 2019 y lanzado oficialmente hasta al menos 1.13 en agosto 2019. Esto pone el lanzamiento potencial más temprano 18 meses después de que @rsc comenzó a discutirlo por primera vez. Por supuesto, no debemos apresurarnos innecesariamente, pero como dijo @Merovius anteriormente, muchas personas, incluido yo mismo, consideramos que una respuesta oficial a la gestión de dependencias es un problema "urgente". Esperar 18 meses me parece excesivo.

Ciertamente parecía que dep iba a ser la respuesta oficial y convertimos nuestros repositorios a ella (y estamos satisfechos con los resultados). Con esta propuesta descartando efectivamente dep para uso a largo plazo, pero sin una forma oficial de comenzar a integrar vgo (al menos hasta que se fusione #25069), nos quedamos en la posición insatisfactoria de vernos obligados a use una herramienta (con dep ) que sabemos que tiene una vida útil muy limitada.

FWIW, absolutamente creo que deberíamos avanzar con esto integrando vgo como una propuesta en 1.11 e incluyendo #25069 en 1.11 (y como lanzamientos de parches a 1.9 y 1.10 tras el lanzamiento de 1.11 ).

Sinceramente, no asimilo todas las implicaciones de MVS y las preocupaciones de @sdboyer al respecto. Sin embargo, considerando su experiencia en este espacio, creo que esas preocupaciones merecen una consideración seria. Dicho esto, si está de acuerdo con la integración vgo con MVS en 1.11 (mientras entiende que su propuesta [todavía en evolución], si se acepta [por 1.12 ], no debe romper los módulos diseñado originalmente para MVS), entonces no veo ninguna razón para no seguir adelante.

También me gustaría agradecer a @rsc por esta propuesta. Aprecio que Go no solo haya copiado el enfoque de otra herramienta y esté tratando de abordar este problema de una manera que parece idiomática. Si bien la gestión de dependencias nunca es divertida, ciertamente parece que, con esta propuesta, Go tiene el potencial de impulsar la industria y posiblemente incluso superar los sistemas que actualmente se consideran los mejores de su clase.

Solo para agregar mi $.02, mi opinión es que MVS es un momento "ah, ja" para la gestión de dependencias. Aprecio la cantidad de pensamiento que la gente ha puesto al respecto, pero sigo convencido de que MVS es a donde debe ir.

Estoy especialmente de acuerdo con los puntos que otros han planteado: las "correcciones automáticas de seguridad" son una quimera en el mejor de los casos y una enorme lata de gusanos en el peor.

Además, estoy con @joshuarubin : una respuesta oficial a la gestión de dependencias es un problema urgente. Otros han comentado que podríamos avanzar con MVS ahora y luego cambiar a otras soluciones si es necesario; si eso es posible, creo que es la mejor manera de hacerlo.

Propongo desacoplar las versiones principales de las rutas de importación de la siguiente manera. (Creo que he tenido en cuenta el razonamiento en vgo-import y que no degrade los logros de vgo que se indican allí). Esto está inspirado en la idea de #25069 de que go build en Go 1.9 y 1.10 debería aprender a interpretar creativamente las rutas de importación (soltando la parte de la versión); en mi propuesta, el viejo go build no cambia, pero vgo aprende un truco similar.


Sintácticamente, los únicos cambios son que:

  1. En archivos .go , import "repo/v2/pkg" sigue siendo import "repo/v2/pkg" si v2 es un directorio, pero se convierte en import "repo/pkg" lo contrario. Esto mantiene la compatibilidad con el go get actual.
  2. En archivos go.mod , module "repo/v2" permanece igual si está en el subdirectorio v2 , pero se convierte en module "repo" si está en el nivel superior. (Este es el prefijo de importación canónico).
  3. En archivos go.mod , también puede escribir require repo v2.3.4 as repo2 . Luego, en los archivos .go usará import "repo2/pkg" (o import "repo2/v2/pkg" si v2 es un directorio). Esto no será importable por el actual go get (a menos que use algo como require github.com/owner/project v2.3.4 as gopkg.in/owner/project.v2 ), pero esto solo es necesario cuando desea usar varias versiones principales en el mismo módulo y la dependencia no almacene las versiones principales en subdirectorios, que de todos modos no pueden ser compatibles con el go get actual.

Técnicamente, esto te permite escribir go.mod con:

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

pero la selección de versión mínima resolverá esto de manera que tanto repo como repo1 se refieran al repositorio en v1.1.1 y repo2 y repo3 a v2.3.3 . No sé si este alias debe permitirse o prohibirse.


ventajas:

  • el código compatible con módulos será compatible con el go get actual, incluso con versiones anteriores a la v2.0.0; como consecuencia:

    • no es necesario que go get tenga en cuenta mínimamente el módulo (#25069)

    • los proyectos anteriores a la versión 2.0.0 no tendrán que romper la compatibilidad con el go get que desconoce el módulo

  • los proyectos no tendrán que esperar a que sus dependencias se conviertan en módulos antes de convertirse en módulos [1]
  • no es necesario desaprobar los proyectos que desconocen el módulo o desalentar a los autores de iniciar nuevos proyectos que desconocen el módulo
  • es más fácil mantener el soporte para el flujo de trabajo sin versiones del actual go get (explicado aquí y más arriba )

Desventajas:

  • puede ser un inconveniente mantener la promesa de que los archivos go.mod ya escritos seguirán funcionando (a menos que el nuevo archivo del módulo tenga un nombre diferente a go.mod )

Ambivalencias:

  • la misma ruta de importación en diferentes módulos puede referirse a diferentes versiones principales

    • bueno: más fácil de mantener después de v2.0.0 y en el cambio de versión principal

    • malo: no sabes qué versión principal usas sin mirar go.mod

  • los módulos pueden definir prefijos de importación arbitrarios para usar dentro de su código

    • algunos usuarios elegirán importar todo con un nombre corto (por ejemplo import "yaml" con require gopkg.in/yaml.v2 v2.2.1 as yaml )

[1] Actualmente vgo puede admitir correctamente dependencias no modulares siempre y cuando ninguna dependencia transitiva no modular de un módulo haya pasado la v2.0.0. De lo contrario, el proyecto tiene que esperar a que todas las dependencias que dependen indirectamente de un proyecto anterior a v2.0.0 se conviertan en módulos.

Realicé un análisis de los archivos Gopkg.toml que pude encontrar de los paquetes en https://github.com/rsc/corpus y escribí un resumen en https://github.com/zeebo/dep-analysis. Según los datos allí, parece que no hay mucha evidencia de que vgo no pueda manejar casi todos los casos de uso identificados.

Realmente espero que esto ayude a reducir el miedo en la comunidad y a que llegue a un acuerdo de que debemos seguir adelante con la propuesta tal como está, recordando que habrá 6 meses adicionales para obtener una experiencia real con la herramienta y hacer los cambios necesarios para solucionar los problemas que puedan surgir.

Si te cito:

Casi la mitad de todas las restricciones en realidad no son restricciones en absoluto: apuntan a la rama principal.

Esto probablemente se deba a que solo existe el maestro y no hay etiquetas o "ramas con nombre como v2, v3". Si ese es el caso, entonces la comparación no es justa porque no tiene otra opción.

@mvrhov No estoy seguro de lo que quieres decir con "no es justo". Me parece que vgo y dep manejarían bien ese caso. O más bien, cualquier alternativa realista tendría que manejar ese caso bien. En particular: si aún no hay una versión lanzada, en un mundo vgo podrían etiquetarse como v1.0/v0.x y no sería necesario cambiar ninguna ruta de importación (la principal idiosincrasia de vgo).

El punto del análisis, por lo que puedo decir, es tratar de estimar el dolor del mundo real causado por los diferentes enfoques. No veo cómo este caso introduce dolor real para nadie.

Esta propuesta ha estado abierta con debates activos durante más de dos meses: @rsc y @spf13 realizaron sesiones de comentarios y recopilaron valiosos aportes de la comunidad que resultaron en revisiones de la propuesta. @rsc también ha realizado reuniones semanales con @sdboyer para obtener más comentarios. Se han proporcionado valiosos comentarios sobre la propuesta que han resultado en revisiones adicionales. Cada vez más, esta retroalimentación se refiere a la implementación que la acompaña en lugar de a la propuesta. Después de una revisión considerable, sentimos que es hora de aceptar esta propuesta y dejar que el amplio ecosistema de implementadores de herramientas de Go comience a realizar ajustes críticos para que nuestra base de usuarios pueda tener la mejor experiencia posible.

Ha habido dos objeciones a esta propuesta de las que creemos que deberíamos hablar:

  1. La propuesta requerirá que las personas cambien algunas de sus prácticas sobre el uso y la liberación de bibliotecas.
  2. La propuesta no logra dar una solución técnica a todos los posibles escenarios que puedan presentarse en relación con las incompatibilidades.

Estos son precisos en su observación pero funcionan según lo previsto. Los autores y usuarios de código _tendrán_ que cambiar algunas de sus prácticas sobre el uso y la liberación de bibliotecas, al igual que los desarrolladores se han adaptado a otros detalles de Go, como ejecutar gofmt. Cambiar las mejores prácticas es a veces la solución correcta. De manera similar, vgo no necesita manejar todas las situaciones posibles que involucran incompatibilidades. Como señaló Russ en su charla reciente en Gophercon Singapur , la única solución permanente a la incompatibilidad es trabajar juntos para corregir la incompatibilidad y mantener el ecosistema del paquete Go. Las soluciones temporales en una herramienta como vgo o dep solo necesitan funcionar el tiempo suficiente para que los desarrolladores tengan tiempo de resolver el problema real, y vgo hace este trabajo lo suficientemente bien.

Agradecemos todos los comentarios y la pasión que ha aportado a este problema crítico. La propuesta ha sido aceptada.

— El Comité de Revisión de Propuestas Go

Para agregar algo de color al registro, las reuniones semanales con @sdboyer no deben verse como un respaldo. Sam recientemente comenzó a escribir sobre los problemas con MVS junto con las cosas que le gustan de vgo . Estoy agregando esto para asegurarme de que no haya problemas de comunicación con nadie más que venga. Si quieres su opinión por favor lee sus palabras. Mi opinión es que contienen una buena cantidad de desacuerdo con el enfoque actual previsto.

@mattfarina FWIW, leí esa oración más como "somos conscientes de sus críticas (como las expresó en privado) y no cambió nuestra opinión". Sin embargo, es lamentable que sus opiniones y argumentos no sean públicos en este momento.

Se siente irresponsable aceptar una propuesta mientras aún existen preocupaciones fundamentales sobre el enfoque. El consenso entre el autor y el experto en dominios comunitarios @sdboyer parece un estándar mínimo razonable a alcanzar antes de que se considere aceptada la propuesta.

@merovius Varios de nosotros hemos compartido opiniones en público y en privado. Varias personas sienten que los problemas planteados fueron aplastados (a veces de manera grosera) en lugar de recibir soluciones suficientes. Estoy empezando a compartir problemas prácticos públicamente para que podamos intentar resolverlos. Por ejemplo, justo hoy comparto algunos detalles sobre un problema práctico aquí . Nota al margen divertida, esto estaba en la portada de las noticias de hackers al mismo tiempo que se marcó como aceptado.

@peterbourgon Como una persona que realizó la encuesta Go Dependency Management y que trabajó en Glide, donde escuché las necesidades que tenían las personas y traté de hacer que funcionara, puedo mostrar problemas prácticos (en lugar de solo opiniones). Es decir, puedo hacer coincidir los deseos, las necesidades y las expectativas de los usuarios con las soluciones para esos problemas. Mi preocupación es la falta de coincidencia en la ruta actual de vgo. Hay necesidades insatisfechas y problemas pragmáticos debido a las diferencias en la forma en que las personas manejan la dependencia.

Una manera fácil de comenzar a aliviar mis preocupaciones es hacer que vgo funcione para Kubernetes a satisfacción de Tim Hockins.

Una manera fácil de comenzar a aliviar mis preocupaciones es hacer que vgo funcione para Kubernetes a satisfacción de Tim Hockins.

¿Hacer que vgo funcione para Kubernetes hoy o hacer que vgo funcione para Kubernetes en los próximos años? Tal como lo entiendo, uno de los desacuerdos de diseño fundamentales entre vgo y dep es si necesitamos trabajar con el ecosistema tal como existe hoy (suposición de dep) o si podemos cambiar la comunidad para hacer lanzamientos etiquetados y mantener la compatibilidad (suposición de vgo) .

Por lo tanto, es posible que vgo no funcione para Kubernetes que usan muchas dependencias durante algún tiempo, hasta que cambien las normas de la comunidad Go.

@mattfarina Claro. Sin embargo, personalmente, me resulta muy frustrante pintar esto como un "rodillo de vapor". @sdboyer se ha abstenido en gran medida de la discusión pública durante meses y todavía no hay argumentos reales y concretos de él. Tenía sus razones y eso es justo. Pero el consenso aún requiere discusión y, al menos en lo que respecta al registro público, personalmente no estoy al tanto de ningún problema que haya sido planteado y simplemente ignorado (aunque todavía no he leído su publicación).

En lo que a mí respecta, cualquier discusión se llevó a cabo a puerta cerrada. Y dado que no tenemos ninguna información de ninguna manera, consideraría justo asumir que ambas partes recibieron la consideración adecuada.

@bradfitz SemVer es utilizado por Go pacakges hoy en día, generalmente en PHP, en node.js, en Rust y en muchos otros lenguajes. Es algo bastante común. He encontrado problemas en estos idiomas y más donde los paquetes se rompieron debido a problemas de compatibilidad con SemVer. A veces intencionalmente y a veces por accidente. ¿Qué hará Go de manera diferente para evitar un problema presente en todos estos otros idiomas porque las personas son falibles?

Si no podemos articular eso, es una mala suposición que la compatibilidad siempre se mantendrá y que los desarrolladores no deberían tener perillas accesibles para ajustar eso y pasar esa información al árbol de dependencia.

Creo que todos estarán de acuerdo: la situación actual con la gestión de dependencias es terrible, en cualquier idioma/plataforma. Creo que @bradfitz explicó correctamente el punto principal del conflicto. Tal vez vgo no tenga éxito, pero para mí es obvio que tenemos que cambiar algo (quiero decir, no solo en Go, sino en general), y vgo parece muy prometedor para intentarlo.

@mattfarina Planeamos intentar implementar un servicio que controlará automáticamente si la compatibilidad se mantiene realmente. Integrarlo con godoc.org, proporcionar insignias para README, usarlo como un proxy para ir a buscar: hay muchas maneras en que podemos intentar que funcione lo suficientemente bien. Claro, @sdboyer tiene razón acerca de que la compatibilidad de la API no garantiza la compatibilidad real, pero es un buen comienzo y debería funcionar lo suficientemente bien en la mayoría de los casos.

Por lo tanto, es posible que vgo no funcione para Kubernetes que usan muchas dependencias durante algún tiempo, hasta que cambien las normas de la comunidad Go.

La esperanza no es una estrategia, especialmente cuando los comportamientos y expectativas existentes ya están bien establecidos. Go podría haber tenido tokens de innovación para gastar aquí si tuviéramos esta discusión hace cinco años, y las cosas eran más susceptibles de influir. Pero como consecuencia de ignorar el problema durante tanto tiempo, me parece claro que cualquier herramienta que se proponga ahora debe satisfacer a los usuarios donde se encuentren.

¿Qué hará Go de manera diferente para evitar un problema presente en todos estos otros idiomas porque las personas son falibles?

Hemos estado discutiendo algún tipo de comando go release que facilita los lanzamientos/etiquetados, pero también verifica la compatibilidad de la API (como el verificador de go tool api interno de Go que escribí para los lanzamientos de Go). También podría consultar godoc.org y encontrar personas que llamen a su paquete y ejecutar sus pruebas contra su nueva versión también en el momento del lanzamiento previo, antes de que se envíe cualquier etiqueta. etc

encuentre a las personas que llaman de su paquete y ejecute sus pruebas contra su nueva versión también en el momento previo al lanzamiento, antes de que se envíe cualquier etiqueta. etc

Esto no es realmente práctico para nadie que no sea Google.

Esto no es realmente práctico para nadie que no sea Google.

Con todos los proveedores de la nube comenzando a ofrecer contenedores como servicio de pago por segundo, no veo ninguna razón por la que no podamos proporcionar esto como una herramienta de código abierto que cualquiera puede ejecutar y pagar los $ 0.57 o $ 1.34 que necesitan. para ejecutar un bazillion de pruebas en un montón de hosts durante unos minutos.

No hay mucha salsa secreta de Google cuando se trata de ejecutar pruebas.

Con todos los proveedores de la nube comenzando a ofrecer contenedores como servicio de pago por segundo, no veo ninguna razón por la que no podamos proporcionar esto como una herramienta de código abierto que cualquiera puede ejecutar y pagar los $ 0.57 o $ 1.34 que necesitan. para ejecutar un bazillion de pruebas en un montón de hosts durante unos minutos.

Esto requiere una cuenta con un proveedor de nube específico, requiere que acepte los términos de servicio de un proveedor de nube específico (que puede o no puede hacer por razones legales, incluso si la mayoría del mundo lo trata como si no fuera así). asunto), requiere que usted viva en un área a la que presta servicios el proveedor de la nube (por ejemplo, si está en Irán y el proveedor de la nube está en los Estados Unidos, es posible que no pueda usarlo debido a las leyes de exportación), y requiere que tiene el dinero para pagar al proveedor de la nube (presumiblemente cada vez que realiza un lanzamiento). Puede que no sea mucho dinero, pero eso no significa que todos puedan pagarlo. Si queremos que Go sea inclusivo y usable por una audiencia diversa, esta no parece una buena solución.

/dos centavos

@SamWhited MeteorJS tenía esto funcionando con galaxy, un comando meteor publish incorporado para ejecutar su proyecto en un proveedor de nube. Tal vez estoy malinterpretando el problema planteado, pero su swing parecía estar bien.

@bradfitz ¿Qué pasa si la API no cambia pero sí el comportamiento detrás de ella? Ese es un caso que rompe con SemVer e impacta a quienes lo importan. ¿Cómo detectas esta situación? Pregunto porque lo he experimentado en más de una ocasión.

herramienta de código abierto que cualquiera puede ejecutar y pagar los $ 0,57 o $ 1,34 que necesitan para ejecutar miles de pruebas en un montón de hosts durante unos minutos.

Esto ahora toca el costo. Esto puede sentirse bien para la gente en una ciudad tecnológica en los EE. UU. ¿Qué pasa con las personas en África, América Central u otros lugares que están distribuidos globalmente? ¿Cómo son herramientas como esta generalmente accesibles fuera de los círculos de "élite tecnológica"?

Y, ¿qué pasa con todos los casos de no hacer trabajo de nube pública? On-premise (mucha gente lo hace) o propietario y tiene problemas de confianza. ¿Cómo funcionará esto para ellos? Si tiene una herramienta interna, es posible que no desee filtrar a los servicios públicos las importaciones que está utilizando. Digamos que obtiene sus importaciones de GitHub pero este servicio se ejecuta en Google. ¿La gente se siente bien entregando su árbol de dependencia a Google? Un grupo no lo hará.

También podría consultar godoc.org y encontrar personas que llamen a su paquete y ejecutar sus pruebas contra su nueva versión también en el momento previo al lanzamiento, antes de que se envíe cualquier etiqueta. etc

Tomemos a Kubernetes como ejemplo de esto. Alguien escribe un paquete que se importa a Kubernetes. Entonces, una herramienta tiene que obtener eso y ejecutar todas las pruebas. Algunas partes están diseñadas para ejecutarse en Windows y POSIX. ¿Podemos probar multi-OS/multi-arch (ya que Go maneja eso). ¿Cómo se verá realmente (y costará)?

--

Creo que herramientas como esta pueden ser útiles. No quiero que la gente piense lo contrario. Simplemente no veo cómo resuelven el problema para muchas personas. No son lo suficientemente prácticos o no se adaptan a todas las configuraciones.

Se siente como si estuviéramos tratando de resolver un problema matemático con restricciones conocidas y controlables. Pero, las personas son desordenadas, por lo que necesitamos soluciones tolerantes a fallas.

Para citar a @technosophos hoy:

"Los administradores de versiones no son en realidad herramientas para compiladores o enlazadores ni nada... los administradores de versiones son para personas que colaboran".

Por si sirve de algo, ha escrito más de un administrador de dependencias, ha estudiado a otros y ha hablado con personas que han escrito aún más.

Se siente irresponsable aceptar una propuesta mientras aún existen preocupaciones fundamentales sobre el enfoque. El consenso entre el autor y el experto en dominios comunitarios @sdboyer parece un estándar mínimo razonable a alcanzar antes de que se considere aceptada la propuesta.

Solo para agregar un poco aquí: tenemos un historial en torno al empaque que es tanto no estándar como subóptimo (el ecosistema go get ). Sería mejor renunciar a un administrador de paquetes estándar que lanzar otro go get que empuja a las personas hacia las malas prácticas en nombre de la compatibilidad con la herramienta "estándar". Como alguien que ha estado usando Go desde su lanzamiento público, encuentro esta conversación frustrante y desalentadora, ya que parece que el liderazgo del equipo de Go no ha aprendido las lecciones de los errores cometidos con go get (nee goinstall ).

Hay problemas razonables y prácticos que se han expresado sobre esta propuesta. Deberíamos cambiar la propuesta para abordarlos y no decir simplemente: "funciona según lo previsto". Si no podemos hacerlo bien para 1.11 o 1.12 o 1.13 entonces deberíamos esperar hasta que se pueda hacer bien. Esta propuesta propone un sistema que se comporta significativamente diferente a la mayoría de los otros sistemas y no en el buen sentido.

La razón detrás de MVS parece ser que el enfoque tradicional es NP-Complete. Creo que es una motivación muy pobre. Cuando se trata de problemas NP-Complete, la pregunta principal es: "¿Con qué frecuencia surgen las instancias difíciles ?" Con la administración de paquetes, la respuesta parece ser "muy rara vez". No debemos conformarnos con una formulación del problema incompleta e inútil solo para evitar la etiqueta NP-HARD en el problema.

La mayoría de los puntos concretos han sido expresados ​​por otras personas más cercanas al tema ( @sdboyer @peterbourgon @mattfarina etc...). Mi principal queja es que estamos aceptando esta propuesta cuando estos puntos concretos no se han abordado adecuadamente.

@SamWhited , está en desacuerdo con una característica opcional de un diseño hipotético. El usuario hipotético que no confía en ningún proveedor de nube o no puede usar ningún proveedor de nube dentro del firewall de su país o no quiere pagar siempre puede ejecutar pruebas (o una fracción de ellas) en su propia máquina durante la noche. O simplemente use la comprobación de firmas go release , que le permite realizar el 95 % del camino de forma gratuita.

@mattfarina , @SamWhited , pasemos la discusión a https://github.com/golang/go/issues/25483.

@mattfarina

He encontrado problemas en estos idiomas y más donde los paquetes se rompieron debido a problemas de compatibilidad con SemVer. A veces intencionalmente y a veces por accidente. ¿Qué hará Go de manera diferente para evitar un problema presente en todos estos otros idiomas porque las personas son falibles?

Todavía no me queda claro por qué se supone que vgo funciona peor en estos casos que dep. Por el contrario, me parece que vgo funciona estrictamente mejor . En su publicación de blog, menciona un problema específico con el timón, como evidencia de la falla del modelo vgo. Sin embargo, en el mundo vgo, hay dos escenarios por los que vgo habría elegido usar v1.4.0 para grpc:

  1. Los desarrolladores de helm optaron por especificar grpc >= v1.4.0 en go.mod como requisito. En ese caso, simplemente pueden revertir este requisito y volver a una versión anterior de grpc que funcione para ellos.
  2. Los desarrolladores de una dependencia de helm optaron por especificar grpc >= v1.4.0 . En ese caso, dep también lo habría instalado y si helm intentara retroceder restringiendo grpc < v1.4.0 dep tendría que croar debido a los requisitos en conflicto.

Entonces me parece que vgo resuelve este problema al menos tan bien como lo haría dep. Mientras tanto, en un mundo profundo, hay otra opción:

  1. Las dependencias transitivas de helm requerían grpc >= v1.x.0 , con algunos x < 4 , luego grpc lanzaron v1.4.0 y el departamento decidió usar la versión más nueva en la instalación, sin que se lo pidieran. . En este caso, el timón estaría roto y necesitaría reunirse para realizar una publicación de corrección de errores (como se describe en su publicación), lo que crearía un gran esfuerzo. Mientras tanto, vgo simplemente habría ignorado la nueva versión y las cosas continuarían funcionando bien.

Aparentemente estoy pasando por alto algo básico. Pero la última vez que pedí una aclaración sobre esto en Slack, me remitieron a una futura publicación de blog hipotética. De ahí mi frustración, porque realmente no entiendo de dónde viene la idea de que vgo de alguna manera tiene más problemas con las personas que rompen la semántica de sus versiones que dep.

Para aclarar, no se trata de dep . Es un análisis de cómo se comporta MVS (vgo) en comparación con otras soluciones de administración de paquetes basadas en SAT-solver (dep incluido).

Otro ejemplo de Matt dice lo siguiente:

Eres el desarrollador del módulo app y tienes dos dependencias:

  • grpc [>= 1.8 ]
  • helm , que tienen la siguiente dependencia:

    • grpc [>= 1.0, < 1.4] (porque grpc introdujo un cambio importante en 1.4).

La mayoría de la gente no sabrá acerca de los requisitos de dependencia transitiva ( helm -> grpc [>= 1.0, < 1.4]) porque eso requeriría ser consciente de que helm se rompe cuando usando grpc >= 1.4. Supongo que eso no es algo que a la mayoría de la gente le importe o que dedique tiempo y energía a investigarlo.

Si está utilizando vgo (confiando específicamente en MVS), obtendrá:

  • helm
  • grpc [>= 1.8 ]

Esa debería ser una combinación inválida (dado que los requisitos helm no se cumplen) y la mayoría de los gerentes de departamento darían un mensaje de error indicándole que tiene un conflicto (dado que helm ha establecido sus requisitos en algunos formato).

Este es un punto significativo de crítica de MVS y vgo. No quiere permitir que las dependencias indiquen cuándo tienen un problema con una versión específica para evitar la necesidad de una resolución completa de SAT . Puede consultar las secciones Theory y Excluding Modules en el artículo de MVS para obtener más explicaciones.

MVS no quiere reconocer esta posibilidad (o al menos quiere restringir la capacidad de dictarlo al módulo actual) bajo el supuesto de que SemVer siempre se respeta y, por lo tanto, no es necesario, lo que prácticamente no siempre es el caso. Me referiría a su artículo sobre compatibilidad con versiones anteriores para mostrar por qué adherirse a la compatibilidad con versiones anteriores es difícil y no es práctico cuando se lo fuerza a la manera vgo.

La solución de MVS es pedirle al desarrollador del módulo que especifique qué versiones excluir, ignorando el conocimiento que pueden compartir los autores de las dependencias sobre estas incompatibilidades. Transfiriendo así la responsabilidad al desarrollador de conocer y hacer la lógica intrincada por la que pasan la mayoría de los gerentes de departamento para descubrir qué versiones de qué dependencias son compatibles entre sí (es decir, una solución SAT).

A menos que las personas comiencen mágicamente a ajustarse a SemVer, me imagino instalando una dependencia cuando use vgo para transformarse en un ejercicio excéntrico en el que, después de importar un módulo, tendría que verificar un archivo README para copiar la lista de versiones que no son compatibles para incluir en su archivo go.mod . Tenga en cuenta que la instrucción exclude solo toma una versión actualmente.

@Merovius

En la publicación de blog de @mattfarina , describen la actualización intencional de Helm a grpc v1.4.0, es decir, el equivalente a actualizar go.mod . La pregunta no es cómo dep o vgo evitan este problema, sino cómo permiten que el autor de la biblioteca se recupere de él. En el caso de la dep, pueden lanzar un parche que anuncie la restricción grpc<v1.4.0 . Para los usuarios que no tienen ninguna otra dependencia de grpc, esto funcionará. Si un usuario ya se actualizó a la última versión de helm y posee otra dependencia en grpc>=v1.4.0 , esta restricción hará que su compilación falle; no es ideal, pero es mejor que el comportamiento de tiempo de ejecución sutilmente roto.

Con vgo , ¿los mantenedores de Helm tienen opciones equivalentes disponibles? Si un usuario ha actualizado grpc a v1.4.0 por cualquier motivo, MVS siempre elegirá [email protected] , Helm se romperá y no hay nada que los mantenedores de Helm puedan hacer al respecto (sin ajustarse al cambio de comportamiento, que a menudo es pérdida de tiempo). No puedo hablar por @mattfarina , pero así es como leo la inquietud planteada y es una que comparto. Con dep y sistemas similares, las bibliotecas intermedias pueden defenderse (o más a menudo, recuperarse) de las infracciones de compatibilidad con restricciones de límites superiores.

@ibrasho @mattfarina

Parece que uno de los ejemplos de Russ en la charla GopherconSG cubre un escenario muy similar (¿quizás idéntico?).

En la publicación anterior, dices que helm depende de "grpc [>= 1.0, <1.4]". Pero eso no es estrictamente exacto. Creo que lo que quieres decir es que alguna versión específica de helm depende de "grpc [>= 1.0, <1.4]". Digamos que la versión de helm es 2.1.3; presumiblemente, esta versión de helm se lanzó después de grpc 1.4 (de lo contrario, no habría sabido que se marcaría como incompatible con grpc 1.4). El punto de Russ en esa charla es que la versión anterior de helm (digamos 2.1.2), presumiblemente (todavía) no se habría marcado a sí misma como incompatible con grpc 1.4.

En otras palabras, una asignación satisfactoria (según dep) hubiera sido helm = 2.1.2, grpc = 1.8. Dep podría elegir correctamente esta asignación de versión sin error, ya que satisface todas las restricciones en las versiones dadas.

@balasanjay

La versión de Helm no cambia fundamentalmente el ejemplo. [email protected] podría declarar una dependencia en [email protected] y el usuario de helm podría tener una dependencia en [email protected] directamente o a través de algún otro paquete. En este escenario, MVS falla e instala [email protected] y [email protected]. Además, este ejemplo asume que el usuario actualiza intencionalmente a [email protected] (y por lo tanto a [email protected]) y quizás incluso a [email protected] , [email protected] , etc. antes de que se descubra el problema.

MVS rechaza intencionalmente las exclusiones de las dependencias intermedias para lograr sus objetivos teóricos:

Las implicaciones negativas (X → ¬ Y, equivalentemente ¬ X ∨ ¬ Y: si X está instalado, entonces Y no debe estar instalado) no se pueden sumar...

Para este ejemplo, necesitamos expresar, si X= helm>= 2.1.3 está instalado, entonces Y= grpc>=1.4.0 no debe estar instalado, lo cual no podemos hacer por diseño.

En efecto, solo el paquete de nivel superior (mediante la reparación de la rotura) y los usuarios de nivel inferior (mediante la adición manual de exclusiones) tienen algún recurso cuando se infringen las reglas de compatibilidad. Los intermediarios como Helm deben funcionar con todas las versiones futuras de cualquier dependencia, lo que, para mí, reduce significativamente la propuesta de valor de dichas bibliotecas.

Tal vez esto fomente un mejor comportamiento en bibliotecas de uso intensivo como grpc y aws-sdk-go porque todas las partes sentirán la peor parte de cualquier rotura y será más difícil solucionarlo. Sin embargo, no siempre es tan fácil. ¿Qué pasa si la "rotura" no es realmente una rotura, sino un cambio legítimo en el comportamiento que tiene consecuencias no deseadas para algunos usuarios, pero es útil para otros? Ese tipo de cosas no es poco común y los autores de aguas arriba dudarían legítimamente en revertir un cambio en ese escenario.

No creo que haya sido tan claro como Russ. Déjame intentar de nuevo.

Inicialmente, el estado de deps se ve así.
Timón 2.1.2: grpc >= 1.0

Luego, se lanza grpc 1.4. Los desarrolladores de Helm se dan cuenta de que existe una incompatibilidad, por lo que impulsan una nueva versión de Helm:
Timón 2.1.3: grpc >= 1.0, < 1.4

Comienzo una nueva aplicación que depende de Helm y alguna característica nueva de grpc (por el bien del argumento). Enumero las siguientes dependencias:
Timón >= 2.0.0
grpc >= 1.4

La afirmación anterior era que dep se daría cuenta del conflicto inherente y reportaría un error.

Pero Russ señaló que eso no es cierto, porque hay una asignación de versión sin conflictos. Específicamente, dep podría elegir usar helm 2.1.2 y grpc 1.4. Según dep, esta es una asignación válida, porque helm 2.1. 3 es el que es incompatible con grpc 1.4, mientras que 2.1. 2 es compatible con todos los grpc >= 1.0.

En otras palabras, el dep podría elegir _válidamente_ "arreglar" un conflicto, degradando a una versión que aún no había registrado el conflicto. Si tiene versiones inmutables, esto parece inevitable. Por lo tanto, parece que dep también manejaría mal https://codeengineered.com/blog/2018/golang-vgo-broken-dep-tree/.

@balasanjay Claro, pero finalmente Helm lanza 2.2.0 con una característica nueva y ordenada que desea, e intenta actualizar, y luego surge el problema.

(Soy cautelosamente optimista de que esto funcionará bien si vgo tiene un UX bien diseñado para que las personas se den cuenta de que su resultado de MVS tiene un "conflicto" de esta forma. Por "bien diseñado" quiero decir que alienta a las personas a lidiar con el problema en lugar de estar bien con muchas advertencias todo el tiempo).

Ciertamente estoy de acuerdo en que hay situaciones en las que dep detectará un conflicto, pero solo quería dejar en claro que _no_ es el que se presenta en esa publicación de blog (o al menos, no con los requisitos de la versión que se presentan actualmente).

Y FWIW, creo que es razonable cuestionar la efectividad de una salvaguarda si se rompe en un ejemplo relativamente simple de un conflicto.

Para que conste, rastreé el ejemplo de Russ (es bastante idéntico a este, en un grado impresionante): https://youtu.be/F8nrpe0XWRg?t=31m28s

Re: selección de versión mínima, tengo problemas para descubrir cómo resolver la siguiente situación:

Imagine una biblioteca popular en modo de mantenimiento, por ejemplo, v1.2.3 ha estado disponible durante más de un año sin cambios. Muchas otras bibliotecas dependen de él.
Llega un desarrollador y se da cuenta de una optimización de velocidad para hacer en v1.2.3. ¡Acelera la función principal de la biblioteca en 10 veces, sin cambios en la API! Esto se publica como v1.3.0. No se encuentran más errores en este paquete para el año siguiente.

¿Cómo terminan recibiendo esta actualización los dependientes? Pueden funcionar con v1.2.3, pero evidentemente v1.3.0 es mejor.

@daurnimator

¿Cómo terminan recibiendo esta actualización los dependientes?

Cada aplicación necesitaría establecer 1.3.0 como la versión mínima para usar.

Bueno, ¡qué día tan tonto es hoy! 😄

Esta propuesta ha estado abierta con debates activos durante más de dos meses.

Este problema ha estado abierto durante años, y la línea de tiempo que rsc estableció para todo esto fue artificialmente corta, considerando todas las cosas.

Ha habido dos objeciones a esta propuesta de las que creemos que deberíamos hablar:

  1. La propuesta no logra dar una solución técnica a todos los posibles escenarios que puedan presentarse en relación con las incompatibilidades.

Si esto es una alusión a las posiciones que le he esbozado a Russ, es una caricatura engañosa. Una de las razones por las que me tomó tanto tiempo organizar mis pensamientos sobre este tema es porque el uso repetido de argumentos y declaraciones engañosas es... francamente, desestabilizador.

Literalmente, nadie piensa que se pueden cubrir TODOS los escenarios posibles. El problema es, y siempre ha sido, que MVS solo resuelve un problema _ilusorio_ (evitando SAT), crea _nuevos_ problemas en su lugar que importan mucho más en la práctica, y no puede funcionar de manera efectiva como una capa intermedia en la que podemos operar razonablemente.

Estos son precisos en su observación pero funcionan según lo previsto. Los autores y usuarios de código tendrán que cambiar algunas de sus prácticas sobre el uso y la publicación de bibliotecas, al igual que los desarrolladores se han adaptado a otros detalles de Go, como ejecutar gofmt.

No se ayuda en nada trivializando el grado de cambios que se proponen aquí comparándolos con la ejecución de gofmt, posiblemente la actividad más insensata que realizamos como desarrolladores de Go.

Como señaló Russ en su charla reciente en Gophercon Singapur, la única solución permanente a la incompatibilidad es trabajar juntos para corregir la incompatibilidad y mantener el ecosistema del paquete Go. Las soluciones temporales en una herramienta como vgo o dep solo necesitan funcionar el tiempo suficiente para que los desarrolladores tengan tiempo de resolver el problema real, y vgo hace este trabajo lo suficientemente bien.

Seamos claros: lo que importa es la _comunidad_. Nosotros. Las personas que producen el ecosistema de software. Llegamos a un mejor ecosistema creando herramientas que nos ayuden a gastar nuestros tokens limitados en colaboraciones útiles, no creando herramientas frágiles que nos castiguen por participar en primer lugar.

@Merovius :

Me remitieron a una hipotética publicación de blog en el futuro. De ahí mi frustración, porque realmente no entiendo de dónde viene la idea de que vgo de alguna manera tiene más problemas con las personas que rompen la semántica de sus versiones que dep.

Reunir todos estos argumentos lleva tiempo y no es mi trabajo diario. Tenía como objetivo terminar esta noche, pero todavía estoy en mi pase de edición final. 😢¿Mañana por la mañana...? ¡Nada está escrito en piedra!

El problema es, y siempre ha sido, que MVS solo resuelve un problema ilusorio (evitando el SAT),...

Respetuosamente, en mi humilde opinión, la solución SAT no es una solución, por lo tanto, para mí, MVS resuelve un problema muy real.

En mi humilde opinión, la solución SAT no es una solución, por lo tanto, para mí, MVS resuelve un problema muy real.

¿Me encantaría entender el razonamiento detrás de eso, si es posible?

Este problema ha estado abierto durante años, y la línea de tiempo que rsc estableció para todo esto fue artificialmente corta, considerando todas las cosas.

Veo aquí dos ideas claramente contradictorias. Las encuestas han demostrado repetidamente que la gestión de la dependencia necesita una solución cuanto antes. Sin embargo, un plazo de seis meses no es suficiente para revisar y aprobar una propuesta.

Entiendo que no debemos elegir la primera solución a implementar. Pero el tiempo es uno de los factores. La contrapropuesta a vgo aún no está bien definida y es muy probable que tarde años en materializarse. Preferiría vgo en Go 1.11 en lugar de una solución basada en SAT súper increíble en Go 1.14 cualquier día.

Esto también supone que lo que implementa vgo está escrito en piedra. Por lo que sabemos, vgo podría cambiar considerablemente durante las ventanas 1.12 y 1.13.

¿Me encantaría entender el razonamiento detrás de eso, si es posible?

Es el mismo razonamiento que está detrás de preferir la expresión regular de Go a PCRE, es decir. no permitir que un programa dependa de un algoritmo que tenga una complejidad cuadrática/exponencial en el peor de los casos.

Debemos tener en cuenta que vgo solo reemplazará go get nada más nada más. Deberíamos comparar vgo con go get y no vgo con algo que no existe. "Peor es mejor"! Centrémonos ahora en los detalles de implementación.

FWIW, en mi opinión, es completamente posible introducir límites superiores sin tener un solucionador SAT completo; simplemente no es posible que la solución generada sea óptima o garantizar que se encontrará una solución existente. Si es necesario, puede

  1. Hacer posible especificar límites superiores
  2. Ignórelos cuando resuelva a través de MVS
  3. Verifique la solución encontrada contra todos los límites y croar si no encaja (esta es la diferencia clave: los enfoques tradicionales intentarían encontrar una solución diferente en su lugar)

Entonces, esto significaría que obtiene las ventajas de MVS (un algoritmo simple sin tiempos de ejecución patológicos), conservando la posibilidad de marcar incompatibilidades y detectarlas estáticamente, pero está renunciando a la garantía de encontrar siempre una solución si existe. Aunque se puede argumentar que la solución que encontraría no es en realidad una solución de todos modos, porque la incompatibilidad sigue ahí, simplemente desconocida para el algoritmo.

Entonces, al menos para mí, parece que es perfectamente posible actualizar de alguna manera para obtener límites superiores en MVS. Todavía no estoy convencido de que sea realmente necesario, pero si ese fuera el caso, siempre se puede agregar más tarde. Hacer que la afirmación "MVS es fundamentalmente no apta" sea problemática. Pero todavía podría malinterpretar el problema. ¿Y puede haber un escenario de falla que lo ilustre mejor?

@sdboyer No te preocupes. Como dije, entiendo completamente que este no es su trabajo diario y agradezco el tiempo que se está tomando para participar. Sigue siendo una cuestión práctica de "si no conocemos los argumentos, no podemos hablar de ellos". Me imagino que estás tan frustrado con toda la situación como yo :)

Es el mismo razonamiento que está detrás de preferir la expresión regular de Go a PCRE, es decir. no permitir que un programa dependa de un algoritmo que tenga una complejidad cuadrática/exponencial en el peor de los casos.

@cznic Soy de la opinión de que la gestión de dependencias no es solo un problema técnico, está entrelazada con restricciones y consideraciones sociales. Así que no estoy seguro de compararlo con expresiones regulares (un problema de implementación puramente técnico) y favorecer un algoritmo basado básicamente en la complejidad del tiempo es un enfoque justo.

Veo que algunas personas prefieren MVS porque es más simple y fácil de razonar y es una consideración comprensible si resuelve los otros aspectos del problema en cuestión.

Me preguntaba si la gente tiene otras razones para preferirlo a un algoritmo basado en SAT.

Me preguntaba si la gente tiene otras razones para preferirlo a un algoritmo basado en SAT.

@ibrasho MVS no necesita un archivo de bloqueo.

Me preguntaba si la gente tiene otras razones para preferirlo a un algoritmo basado en SAT.

Personalmente, mis razones son

  1. Unifica el archivo de bloqueo y el manifiesto en un solo archivo, que en gran medida se puede editar por computadora. Lo que significa menos ruido sin dejar de obtener compilaciones reproducibles (o de "alta fidelidad") en el caso común. AFAICT esto es algo exclusivo de MVS. Como una de mis principales frustraciones con otros administradores de paquetes es el trabajo de tener que editar archivos de manifiesto, esto es enorme para mí.
  2. La reparación gradual será más fácil/posible. Como creo firmemente en este enfoque para resolver el problema del desarrollo distribuido, esto también es importante para mí.
  3. Puede ayudar al ecosistema a permanecer colectivamente cerca de HEAD para la mayoría de las bibliotecas. Esto es en gran medida especulación y depende en cierta medida de las herramientas disponibles. Pero si un "extraer todo a la última versión" es lo suficientemente simple, puede aumentar la cadencia con la que las versiones más nuevas de las bibliotecas se prueban entre sí en producción.
  4. Logra todo esto preservando o superando las cualidades deseables de otros enfoques, AFAICT. Las actualizaciones solo ocurren si se desea. Y los paquetes binarios continuarán construyéndose incluso si la construcción de algunas de sus dependencias se rompe en una nueva versión, dando tiempo al autor para trabajar en una solución.

Especialmente esta última parte es algo irónica. Porque esta cualidad exacta se describió como extremadamente importante en la última publicación de @sdboyer , pero en este punto, sigo creyendo que vgo es estrictamente mejor en este sentido que los enfoques tradicionales.

@Merovius
"Unifica el archivo de bloqueo y el manifiesto en un solo archivo"

  • esto no es del todo cierto, ya que los manifiestos están efectivamente dispersos por todos sus archivos. Las declaraciones de importación actúan efectivamente como manifiestos.

@docmerlin Cuando dije "manifiesto", quise decir un archivo que enumera todos los módulos de los que depende con sus versiones apropiadas (en particular, contiene estrictamente más información que las declaraciones de importación, de lo contrario no lo necesitaría). En el caso de vgo sería go.mod , en el caso de dep sería Gopkg.toml . También podría llamarlo el archivo de configuración para el solucionador de dependencias. Si considera que un término diferente es más apropiado, siéntase libre de sustituirlo por manifiesto, cuando lea mi comentario.

Tenga en cuenta que es bastante normal que haya un archivo que enumere todas las dependencias y una lista de importaciones explícitas (que son un subconjunto potencialmente estricto de las dependencias) por archivo. En particular, todos los administradores de dependencias de Go que conozco hacen eso. Otros enfoques también usan un archivo de bloqueo que describe versiones específicas y precisas para garantizar compilaciones reproducibles. Y la característica distintiva de MVS a la que me refería es que este archivo no es necesario, ya que puede derivarse únicamente del archivo manifest/dependency-solver-config/go.mod.

(borrado + vuelto a publicar de mi cuenta personal)

@cznic , el enfoque en las clases de complejidad de MVC frente a un enfoque basado en SAT de forma aislada no tiene sentido (como creo que @sdboyer escribe en alguna parte, nos vemos atrapados hablando de eso porque es una de las pocas cosas que podemos nombre/identificación).

La sugerencia de @bradfitz en el n.º 25483 para abordar algunas de las preocupaciones con vgo (que creo que inicialmente es una loca pero quizás una gran solución práctica) implica ejecutar las pruebas de usuarios arbitrarios de su API antes de un lanzamiento. Este es un problema NP-completo en general, pero en la práctica podría ser una gran solución (al igual que gps2).

Entonces, por un lado, tenemos algoritmos de administración de paquetes basados ​​en SAT y, por otro lado, tenemos un algoritmo en NL que nos obliga a hacer un trabajo NP completo más adelante (o tiempo de espera, que es lo que haría cualquier solucionador práctico de SAT). para archivos de bloqueo contradictorios).

el enfoque en las clases de complejidad de MVC frente a un enfoque basado en SAT de forma aislada no tiene sentido...

No estoy seguro de dónde viene el término 'enfoque'. Es solo que si hay dos algoritmos disponibles, el peor de los casos es cuadrático o peor y el otro es lineal o mejor, elijo el último y evito el primero. Yo lo llamaría un principio, no un enfoque.

... sugerencia en #25483 para abordar algunas de las preocupaciones con vgo ...

Parece que el problema #25483 no está relacionado con vgo. ¿Error de tipografía?

Es solo que si hay dos algoritmos disponibles, el peor de los casos es cuadrático o peor y el otro es lineal o mejor, elijo el último y evito el primero.

@cznic claro, por lo general, si dos algoritmos le dan los mismos resultados, quiere el que tiene menor complejidad (aunque esto ni siquiera es tan simple: Python usa la ordenación por inserción para entradas pequeñas porque a pesar de tener peores límites de complejidad, tiene mejores constantes + tiempo de ejecución hasta un punto).

En este caso (algoritmos basados ​​en MVS vs. SAT), los resultados difieren a propósito y tienen amplias consecuencias. Sugiero que, debido a esto, no puede simplemente comparar la complejidad algorítmica, debe considerar sus impactos más amplios.

Parece que el problema #25483 no está relacionado con vgo

La primera línea de esa edición es un enlace al comentario de Brad en esta edición: https://github.com/golang/go/issues/24301#issuecomment -390788506. Si bien esta herramienta será útil fuera de vgo, parece que se está considerando en gran medida para mitigar algunas de las desventajas de MVS (en mi opinión/entendimiento).

Uf, tantos comentarios. Intentaré agregar algunos detalles e historial para ayudar.

Hace un par de años había una serie de diferentes soluciones de gestión de dependencias (por ejemplo, godep, glide, etc.). Para descubrir un camino a seguir sucedieron algunas cosas:

  1. Un grupo de personas comprometidas y conocedoras se reunió en un comité . Tenga en cuenta que un miembro del equipo Go de Google formaba parte de este grupo.
  2. Un segundo grupo de personas que habían creado administradores de dependencia o tenían información sobre ellos apoyó a este primer grupo.
  3. Se realizó una encuesta de la comunidad sobre las necesidades y opiniones sobre las herramientas existentes (en Go y fuera de Go) . Tenga en cuenta que algunos resultados fueron privados solo para los ojos del comité.
  4. Se entrevistó a empresas que usan Go para la producción para obtener detalles sobre sus necesidades. Los detalles de esto no son públicos para que la gente pueda hablar libremente.

Todos los datos de la encuesta y la entrevista se retroalimentaron al comité. Después de revisar los datos y debatirlos, decidieron que necesitábamos una solución con ciertas características y crearon una especificación . Después de eso, el desarrollo en dep comenzó a satisfacer esas necesidades.

En Gophercon el año pasado hubo una cumbre de contribuyentes que incluyó a personas que estaban involucradas en la gestión de dependencias hablando de ello. Cerca del final de esas conversaciones, Russ se acercó a la mesa y dijo algo como, Puedo hacerlo mejor si voy por mi cuenta y construyo algo. Hizo eso y se le ocurrió vgo. Se hizo por separado de la comunidad.

¿Vgo satisface las necesidades expresadas por las personas en la encuesta y las entrevistas? Por lo que deduzco de Russ, no leyó los resultados pero criticó el proceso. Podría valer la pena que alguien haga un mapeo.

Oh, en la cumbre, Russ compartió una de las razones, en ese momento, no le gustaba un solucionador de SAT. Quería una solución con menos líneas de código porque no quería que el Go Team de Google tuviera que mantener tanto código. Lo recuerdo específicamente porque hice algunas comparaciones de LOC entre profundidad, planeo y otras herramientas después de eso para obtener una mejor idea de las diferencias.

Go es un proyecto de propiedad y ejecución de Google. Si el problema es de recursos, ¿debería Go estar bajo una fundación y personas de otras organizaciones involucrarse en su propiedad? Esa es otra forma de agregar recursos para mantener la cadena de herramientas.

No, #25483 no está relacionado con vgo. Acabo de enumerarlo de antemano como otro tipo de cosa que podría hacer un comando de ayuda hipotético go release . Pero sería útil en cualquier momento.

Mi punto más importante fue que Go nunca ha hecho que sea muy fácil hacer lanzamientos de paquetes Go. En una vida anterior, escribí http://search.cpan.org/dist/ShipIt/ para automatizar los lanzamientos de los paquetes Perl CPAN y marcó una gran diferencia cuando tienes herramientas alrededor de esas cosas en lugar de hacerlo a mano.

Solo mencioné un go release hipotético porque me preguntaron qué podría hacer Go de manera diferente para ayudar a los humanos a no cometer errores.

El único problema real que veo con vgo parece trivial de solucionar... el problema de la versión máxima. Si una biblioteca se rompe con la versión 1.7 de una dependencia, no hay otra forma de especificarlo que no sea una exclusión... lo que solo ayuda hasta que sale la versión 1.8, que probablemente todavía esté rota exactamente de la misma manera.

Parece que sería trivial agregar la versión máxima a vgo solo como una forma de ayudar a vgo a determinar cuándo dos bibliotecas son incompatibles. Si una biblioteca dice que necesita al menos v1.7 y una biblioteca dice que necesita

Sin esto, vgo solo usará 1.7 y una de las bibliotecas se romperá. Si tiene suerte, hay un error del compilador... lo más probable es que solo haya un error de comportamiento sutil que podría pasar desapercibido hasta el final. Y lo insidioso es que probablemente sea alguna dependencia transitiva a la que ni siquiera llamas directamente.

Las restricciones de la versión máxima de @natefinch empujan a MVS fuera de su muy inteligente territorio de evitación de SMT.

Creo que @natefinch significa versiones máximas como verificación/filtro final. Una vez que MVS haya hecho su trabajo, vgo generaría un error si alguna de estas restricciones de versión máxima no se cumpliera. Eso todavía no nos lleva al territorio del solucionador SAT.

Exactamente. No hay solución. Solo hay "vgo dice que 1.7 es lo correcto para usar, pero el módulo X dice que no funciona con esa versión". Esto ya es algo que puede suceder hoy con vgo si tiene algo que dice require foo 1.7 y algo más dice exclude foo 1.7 , si no hay una versión superior de foo.

¿Y entonces qué se supone que debes hacer?

Usas tu cerebro humano para encontrar una solución, porque no hay una solución mecánica. Está tratando de usar dos bibliotecas que afirman categóricamente que requieren versiones incompatibles de una biblioteca. A romperá con 1.6, B romperá con 1.7. El fin.

Debe convencer al autor de la dependencia para que corrija el error (si es un error), convencer a uno de los autores de la biblioteca para que publique una nueva versión que sea compatible con la nueva versión de la dependencia, o bifurcar un montón de cosas y arreglarlo usted mismo. .

No hay una buena respuesta. Pero tampoco hay herramientas en el mundo que puedan arreglar esto por usted.

@sdboyer

El problema es, y siempre ha sido, que MVS solo resuelve un problema ilusorio (evitando el SAT),

No puedo hablar de sus conversaciones privadas con Russ, pero "evitar el SAT" me parece un argumento falso. “Evitar el SAT” no es más un objetivo que “usar el SAT”: ninguno tiene un impacto concreto en los usuarios.

A mi modo de ver, los problemas concretos que resuelve MVS son:

  • hacer compilaciones reproducibles por defecto,
  • construir lo más cerca posible de las versiones probadas, y
  • evitando rechazos espurios.

Llegamos a un mejor ecosistema creando herramientas que nos ayuden a gastar nuestros tokens limitados en colaboraciones útiles, no creando herramientas frágiles que nos castiguen por participar en primer lugar.

Estoy de acuerdo. Pero quiero echar un vistazo más de cerca a sus suposiciones: ¿qué herramientas “castigan” la participación y por qué?

Uno de los ejemplos que diste en tu publicación fue: “Nuestro proyecto depende de [email protected] este momento, pero no funciona con [email protected] o más reciente. Queremos ser buenos ciudadanos y adaptarnos, pero ahora mismo no tenemos el ancho de banda”.


La primera suposición (implícita) que está haciendo es que usted (o sus usuarios) han tenido el tiempo y el ancho de banda para probar su proyecto exhaustivamente en todas las versiones de sus dependencias.¹ Para algunos proyectos, esa suposición en sí misma puede no ser válida. : al establecer la expectativa de que todos etiqueten los límites superiores cuando descubren incompatibilidades, terminas "castigando" a los mantenedores que no tienen el ancho de banda para probar las regresiones y actualizar los límites en potencialmente todos sus lanzamientos.

Por el contrario, bajo MVS, los mantenedores solo están obligados a declarar una cosa: "Probamos a fondo contra [email protected] y funcionó". Si sus usuarios no hacen nada para interrumpir eso, construyen contra [email protected] y todo sigue funcionando como lo hacía antes.

Bajo MVS, la _ruptura solo ocurre en el momento de una actualización explícita._ Ese es un beneficio significativo: si su usuario actualiza alguna otra dependencia para que obtenga [email protected] y interrumpa el uso de su paquete, simplemente puede retroceda esa actualización hasta que tenga tiempo de arreglarla, _o hasta que el mantenedor de X tenga tiempo de corregir la incompatibilidad._ Y dadas las expectativas correctas, lo último puede ser mucho más probable que lo primero: hacer muescas [email protected] puede convertirse en un trabajo innecesario si [email protected] restaura la compatibilidad.


La segunda suposición que está haciendo es que cada incompatibilidad que afecta a _cualquier parte_ de su módulo afecta a _todos los usuarios_ de su módulo. Si la parte de su paquete que se rompe por debajo [email protected] es una función poco utilizada, ¿por qué impedir que sus usuarios actualicen X en su programa que ni siquiera lo llama?

Podría argumentar que si algunas partes del módulo no dependen de otras partes, deberían ser módulos separados, pero eso nuevamente obliga a los mantenedores de paquetes a trabajar más: si solo tengo el ancho de banda para probar y actualizar periódicamente, es posible que solo tenga el ancho de banda para mantener un módulo, no un complejo completo de módulos detallados con dependencias detalladas.


¹ En general, la detección de incompatibilidades con las dependencias requiere que realice una prueba con _el producto cruzado de todas las versiones_ de esas dependencias: es posible que su uso particular de [email protected] esté bien, pero falla en combinación con algún otro paquete del que depende sobre. Por ejemplo, quizás usted y su dependencia requieran opciones incompatibles en una configuración global.

simplemente pueden revertir esa actualización

Eso supone que se trata de un error del compilador o algo similar muy visible. Es mucho más probable que sea un error de comportamiento sutil que no sea evidente de inmediato. Actualiza, ejecuta sus pruebas y todo se ve bien. Tal vez un tiempo de espera que era de 10 segundos ahora es de 30, y eso elimina los tiempos de espera en el resto de su pila cuando está bajo carga. No te darías cuenta hasta que esté funcionando en producción (algo similar nos pasó con un cambio en mgo hace unos años).

Si la parte de su paquete que falla en [email protected] es una función poco utilizada, ¿por qué impedir que sus usuarios actualicen X en su programa que ni siquiera lo llama?

Porque probablemente no sabrán si están usando o no esa función si se trata de una dependencia transitiva, y ¿quién puede decir que alguna ruta de código no utilizada no se activará repentinamente en el futuro cuando cambie su código? Entonces ahora se está llamando a esa función rota. Es mucho mejor confiar en el mantenedor de la biblioteca que es un experto en comprender su propia biblioteca, que si dice que no funciona con 1.7, no cree con 1.7.

Eso supone que se trata de un error del compilador o algo similar muy visible. Es mucho más probable que sea un error de comportamiento sutil que no sea evidente de inmediato.

Hay errores sutiles que acechan en casi todas las versiones de casi todos los paquetes de software. Por lo general, no marcamos los lanzamientos como completamente inutilizables solo porque hayamos encontrado uno de esos errores; en su lugar, lo arreglamos en una versión puntual posterior.

¿Qué hace que esta clase particular de error sea especial?

¿Quién puede decir que una ruta de código no utilizada no se activará repentinamente en el futuro cuando cambie su código?

Ese es exactamente el argumento de MVS: si cambia su código, entonces detecta la rotura _en esa revisión_ y también puede actualizar la restricción de versión en esa revisión.

Eso implica que, como usuario, es más fácil dividir las fallas si actualiza sus dependencias una a la vez en lugar de hacerlo de forma masiva, pero eso es cierto para los cambios en general: cuanto más pequeños sean los cambios, con mayor precisión podrá dividirlos en dos, independientemente de si son cambios en su código o sus dependencias.

¿Qué hace que esta clase particular de error sea especial?

No es solo un error. Es más grande que eso. El autor de la biblioteca, que es el principal experto en su código, le ha dicho al mundo "yo, la versión 1.7 de X rompe mis cosas de maneras que son tan malas, simplemente ni siquiera construyas con él".

Claramente, a menos que sea un error del compilador, es un juicio. Si 99 de sus funciones entran en pánico, pero una no... ¿es solo un error? ¿O es una incompatibilidad total? ¿Qué pasa si es solo una función la que entra en pánico?

En algún momento, un humano tiene que tomar esa decisión. Preferiría lidiar con una incompatibilidad declarada preventiva que ocurre en el momento de la compilación, que preocuparme por un problema importante no declarado que se convierte en producción.

No es solo un error. Es más grande que eso. El autor de la biblioteca, que es el principal experto en su código, le ha dicho al mundo "yo, la versión 1.7 de X rompe mis cosas de maneras que son tan malas, simplemente ni siquiera construyas con él".

El autor de una biblioteca puede expresar esto de otra manera: escriba una prueba que falle cuando se usa con una versión incompatible de X. Esto tendrá la ventaja de no requerir cambios en la biblioteca si X lanza una versión corregida, así como detectar cualquier futuras regresiones.

Escriba una prueba que falle cuando se usa con una versión incompatible de X.

Sí, pensé en eso. Pero luego le está pidiendo a cada binario de nivel superior que ejecute todas las pruebas para todas las dependencias transitivas, pruebas que pueden requerir una infraestructura que usted no tiene. No todos los conjuntos de pruebas están 100 % aislados.

Hay una razón por la que go test ./... no ejecuta pruebas en el directorio de proveedores.

Para resumir (probablemente mal), parece que el principal argumento técnico contra vgo es que debe haber una forma en que las bibliotecas declaren restricciones respetadas globalmente en sus propias dependencias.

¿Por qué no hacer que ambas partes acuerden sancionar una propuesta competidora que explora cómo GPS2 podría encajar con las partes de vgo que les gustan a ambas partes? Luego, fusionar el experimento de vgo mientras tanto y revisar la propuesta de GPS2 antes de que vgo fusione la línea principal.

Como alguien que luchó con muchas herramientas de dependencia en el pasado, estoy emocionado por vgo. FWIW, como miembro de la "comunidad", me siento bien representado por la solución vgo hasta ahora. Sin embargo, sigo abierto a considerar los argumentos a favor de agregar restricciones de versión global y espero que ese argumento se desarrolle más.

Solo tirando esto por ahí:

Eso supone que se trata de un error del compilador o algo similar muy visible. Es mucho más probable que sea un error de comportamiento sutil que no sea evidente de inmediato. Actualiza, ejecuta sus pruebas y todo se ve bien. Tal vez un tiempo de espera que era de 10 segundos ahora es de 30, y eso elimina los tiempos de espera en el resto de su pila cuando está bajo carga.

Este es un problema en el software en general. NPM (la otra herramienta de control de versiones con la que personalmente estoy más familiarizado) usa un solucionador SAT combinado con una comunidad que ha adoptado fuertemente a semver, y este problema aún existe.

En cuanto a la discusión sobre la dependencia transitiva, la realidad es que no existe una varita mágica: en algún momento, el desarrollador debe ser consciente de las dependencias que usa y dedicar tiempo para probar correctamente el código del que es responsable en última instancia. Mi empleador no puede ser el único en el que estamos obligados a justificar cada biblioteca que usamos, incluidas las bibliotecas transitivas, por razones legales y de otro tipo.

Honestamente, en mi opinión, muchas de las quejas hacia vgo parecen ser "no es perfecto, por lo tanto, no funcionará". No dejemos de implementar una buena solución por falta de una solución perfecta.

Para mí, parece muy alineado con la filosofía general de Go que el equipo central proporcione una herramienta que sea buena en la mayoría de las situaciones, dejando que la comunidad proporcione herramientas más avanzadas y/o específicas.

@malexdev Puede haber un problema con sus actores en el argumento de que:

No dejemos de implementar una buena solución por falta de una solución perfecta.

dep es una buena solución hoy en día. Uno que fue creado por la comunidad trabajando juntos. vgo, como comenzó anteriormente, hace un par de suposiciones:

  1. Que nadie romperá jamás con Semver, ni siquiera por accidente.
  2. Que necesitaremos reelaborar las bases de código existentes en el ecosistema existente

vgo se basa más en la "solución perfecta" en un "mundo perfecto", mientras que dep funciona hoy siguiendo lo que ya funciona en el ecosistema de otros lenguajes de programación y es tolerante a fallas.

Puede ver esto en el historial del espacio de problemas de administración de paquetes que acabo de escribir .

Para resumir (probablemente mal), parece que el principal argumento técnico contra vgo es que debe haber una forma en que las bibliotecas declaren restricciones respetadas globalmente en sus propias dependencias.

Estoy de acuerdo con este resumen.

¿Por qué no hacer que ambas partes acuerden sancionar una propuesta competidora que explora cómo GPS2 podría encajar con las partes de vgo que les gustan a ambas partes?

En este punto, sigo sin estar convencido de que GPS2 sea una necesidad o incluso una buena idea. La capacidad que describió anteriormente se puede adaptar a vgo además de MVS (como this o this ). Personalmente, espero que la próxima publicación de blog de @sdboyer contenga buenos argumentos en contra de MVS, pero en este momento, realmente no veo ninguna razón para un algoritmo diferente, especialmente uno que costaría importantes ventajas de UX de vgo.

Aunque, para ser justos, tampoco veo ninguna razón en contra de experimentar con eso.

dep es una buena solución hoy en día.

No estoy seguro de estar de acuerdo. No lo he usado yo mismo, pero en Slack hay varias personas que se quejan de problemas que parecen directamente atribuibles a su enfoque de resolución de SAT. Y sé que estoy muy descontento con el diseño general de los departamentos (dejando de lado la cuestión del solucionador de dependencias en sí, el flujo de trabajo general y la experiencia de usuario).

  1. Que nadie romperá jamás con Semver, ni siquiera por accidente.

Lo siento, pero he pedido repetidamente la justificación de esta declaración y no obtuve ninguna. ¿Por qué vgo asumiría esto de alguna manera, forma o forma más que dep? Estoy fundamentalmente en desacuerdo con esta afirmación. Es una suposición hecha para explicar el algoritmo. Al igual que si explicara el algoritmo de dep, explicaría las suposiciones integradas en las versiones semánticas. En el peor de los casos, muestran las mismas fallas si no cumple con esa semántica.


Creo que, en general, tiene sentido distinguir entre diferentes partes de lo que estamos hablando. Algunas de las quejas son sobre SIV, algunas MVS y algunas sobre el shell vgo general. Por ejemplo, es cierto que MVS no puede manejar los límites de la versión superior, pero eso no significa que vgo no pueda manejar los límites de la versión superior. SIV requiere cambiar una gran cantidad de código (reescribiendo declaraciones de importación), pero nuevamente, eso ni siquiera significa necesariamente que vgo lo requiera. Aunque para ser claros, tampoco creo que sea tan importante, siempre y cuando podamos migrar. Qué AFAICT podemos.

Acabo de ver el discurso de apertura de GopherConSG de @rsc sobre el control de versiones. Abordó el escenario en el que una dependencia introduce un cambio importante y comparó cómo lo manejarían vgo y dep, lo que parece ser la principal preocupación aquí. (Es un gran reloj.)

Si entendí su punto correctamente, dep también puede romper la compilación si se usa una limitación de versión máxima para evitar una mala versión . Estaría muy interesado en ver este punto abordado por aquellos aquí que están preocupados de que vgo no alcance la profundidad en este sentido.

@willfaught Para nosotros, romper la compilación cuando se usa una limitación de versión máxima para evitar una mala versión se considera un éxito. Esto es lo que queremos que suceda. Russ señala correctamente que este problema no se resuelve automáticamente. Una restricción en Helm>2.0.0 no va a actualizar al usuario automáticamente a " [email protected] ", pero funcionaría correctamente (rebajar grpc o desencadenar un error de compilación si eso es imposible) si el usuario dependiera explícitamente de "Helm ==2.1.4". Personalmente, lo primero que suelo intentar cuando encuentro un problema con una biblioteca es forzar una actualización a la última versión. Con Dep, esto me informaría de la falla introducida por GRPC 1.4.0. Con vgo , la única forma en que Helm me comunica esto es a través de la documentación.

Reitero el punto porque sigue sin entenderse: ni dep ni vgo pueden evitar que ocurra este problema ni dar una solución infalible. Más bien, dep le permite a Helm comunicar que el problema existe, mientras que vgo no lo hace.

Para resumir (probablemente mal), parece que el principal argumento técnico contra vgo es que debe haber una forma en que las bibliotecas declaren restricciones respetadas globalmente en sus propias dependencias.

Agregaría algo de color a este resumen en el sentido de que estas restricciones son necesarias para lidiar con el camino infeliz de cuando se violan las reglas de compatibilidad. vgo establece la regla de compatibilidad de importación y luego procede a desarrollar una solución asumiendo que siempre se sigue esa regla. En este mundo idealizado, la necesidad de límites superiores es limitada o incluso inexistente. En el mundo real, esto no sucederá: los desarrolladores lanzarán actualizaciones que rompan la compatibilidad, ya sea intencionalmente o no.

Creo que @Merovius tiene una solución viable. MVS procedería como se especifica, luego, una vez completada la resolución, vgo verificaría cada paquete resuelto en busca de exclusiones. Si se encuentra alguno, se informa al usuario final, que puede optar por modificar sus dependencias para cumplir con estas restricciones o elegir anular e ignorar las restricciones. Yo también he estado en el otro lado de esto y, a veces, lo sabes mejor que el mantenedor; funciona para su aplicación y eso es todo lo que le importa.

Esto restaura una ruta para que las bibliotecas intermediarias comuniquen una incompatibilidad a los usuarios finales. Para repetir el ejemplo del timón una vez más:

[email protected] : Timón @2.1.2
Timó[email protected] : [email protected]

==> El usuario actualiza a [email protected] intencionalmente.

Usuario: Helm @2.1.3, [email protected] ("Helm actualizado, ¡así que finalmente puedo usar grpc 1.4!")
Timón: GRPC @ 1.4.0

==> ¡Error detectado! El usuario está viendo algunos problemas con Helm, así que busque una nueva versión.

Usuario: [email protected] , [email protected]
Timón: GRPC @ 1.3.5, GRPC débil <1.4.0

El usuario ve una advertencia de que GRPC 1.4.0 es rechazado por la instalación de [email protected]. Dado que Helm no funciona para mí y eso es lo que estoy tratando de arreglar, elimino mi dependencia de GRPC 1.4.0 (lamentablemente, pierdo algunas funciones útiles) y vuelvo a ejecutar MVS. Esta vez, MVS resuelve GRPC en 1.3.5 y Helm en 2.1.4, vuelve a verificar todas las restricciones débiles, encuentra que se cumplen y listo.

No espero que ninguna herramienta resuelva estos problemas mágicamente, pero espero algún recurso como biblioteca de middleware. Por lo que puedo decir, la única opción en vgo es bifurcar y cambiar el nombre de todas mis dependencias ascendentes (o, de manera equivalente, copiarlas en mi proyecto) si quiero aislar a mis usuarios de los problemas de compatibilidad con estas dependencias. No creo que nadie quiera eso.

@willfaught Para nosotros, romper la compilación cuando se usa una limitación de versión máxima para evitar una mala versión se considera un éxito. Esto es lo que queremos que suceda.

El punto señalado en la charla es que vgo no es peor que dep en este escenario. En su ejemplo , la construcción no está rota en el sentido de que dep no puede encontrar una solución; está roto en el sentido de que dep encuentra una solución, y esa solución incluye la versión mala, lo que resulta en la misma situación mala que queríamos evitar.

Realmente debería ver el video, que muestra un excelente ejemplo, pero aquí está la esencia tal como lo entendí/recuerdo:

  • Las versiones del paquete (incluidos sus requisitos de dependencia) son inmutables
  • Para agregar una limitación de versión máxima a una dependencia existente para su paquete, debe publicar una nueva versión de su paquete.
  • Es posible que dep elija la versión anterior de su paquete para satisfacer todos los requisitos, en cuyo caso su nueva limitación de versión máxima no estará presente. Esto permite que la mala versión se use después de todo.

Estoy mayormente de acuerdo con la propuesta de agregar exclusiones máximas de versiones, pero tengo esta preocupación: supongamos que pongo en mi biblioteca "usar gRPC >1.4, <1.8" y luego en gRPC 1.9, los autores deciden, "sabes qué, Helm fue correcto, hicimos un cambio importante en 1.8, estamos volviendo a nuestro comportamiento anterior en 1.9.0". Ahora, las personas que intenten importar Helm+gRPC no podrán usar 1.9 hasta que Helm publique una versión que diga "usar gRPC >1.4, excepto 1.8.0, 1.8.1, 1.8.2, pero 1.9+ es genial".

En otras palabras, tal vez exclude grpc 1.8 sea ​​suficiente porque no sabremos si gRPC 1.9 será incompatible o no hasta que se publique, momento en el que Helm puede agregarlo a la lista de exclusión o no.

No sé esencialmente nada sobre este espacio. Pero al leer la discusión aquí, parece que el mayor desacuerdo se reduce a cómo detectar casos erróneos. Es decir, tanto MVS (vgo) como SAT (dep) manejan situaciones normales más o menos bien, quizás no de manera idéntica, pero lo suficientemente bien.

SAT proporciona una capacidad que MVS no tiene: con SAT, el autor del paquete de biblioteca P1 puede declarar "P1 requiere P2 y funciona con P2Version > 1.1 y P2Version < 1.4". MVS solo puede declarar "P1 requiere P2 y funciona con P2Version > 1.1", y no puede expresar la restricción "P2Version < 1.4". En el caso normal, esto no importa. Solo importa si alguna operación intenta actualizar P2 a la versión 1.4. En ese caso, el SAT reportará un error, mientras que el MVS no lo hará. Al usar MVS, si la incompatibilidad no es un error de compilación, puede causar una falla mucho después del hecho.

Sin duda los partidarios del SAT ven otros problemas importantes con MVS, pero hasta ahora este es el que yo entiendo.

Creo que vale la pena señalar que si las expresiones de restricción están versionadas, si son parte de una versión específica de P1, entonces en el curso normal de los eventos, antes de que se publique la versión 1.4 de P2, la versión 2.2 de P1 felizmente dirá "P2Version > 1,1". Solo cuando se publique la versión 1.4 de P2, los autores de P1 notarán la incompatibilidad y lanzarán la versión 2.3 de P1 con "P2Version > 1.1 y P2Version < 1.4". Entonces, si está utilizando la versión 2.2 de P1, ni SAT ni MVS informarán ningún problema con la actualización de P2 a la versión 1.4, aunque fallará de alguna manera posiblemente sutil.

En otras palabras, si bien tiene mucho sentido que una versión de P1 enumere las versiones compatibles mínimas de P2, si la versión funciona correctamente con la versión más reciente de P2, entonces no tiene sentido que una versión enumere las versiones compatibles máximas. . La versión máxima compatible será conservadora y, por lo tanto, cada vez más incorrecta a medida que aparezcan nuevas y mejores versiones de P2, o si P2 cambia de alguna manera incompatible en el futuro, no especificará ese requisito ya que en el momento del lanzamiento no lo hace. no existo

Entonces, si queremos tener un sistema que defina algo más que los requisitos mínimos de versión, esos requisitos no deben ser parte de una versión específica, sino que deben ser parte de algún tipo de metadatos asociados con el paquete, metadatos que se pueden obtener en en cualquier momento sin actualizar el paquete en sí. Y eso significa que la operación "actualizar este paquete" debe ser independiente de la operación "comprobar si las versiones de mi paquete actual son compatibles".

Afirmaría además, y esto es definitivamente más tenue que lo anterior, que si falla "comprobar si las versiones de mi paquete actual son compatibles", en general no es prudente confiar en ninguna herramienta para resolver el problema. Si el problema de compatibilidad no se puede resolver con la simple operación "actualizar todos los paquetes relevantes a la versión actual", entonces requiere reflexión. Una herramienta puede guiar en ese pensamiento, pero en general no puede reemplazarlo. En particular, parece muy imprudente que una herramienta comience a degradar paquetes automáticamente.

Entonces, si pensamos en términos de

  1. una forma de definir los metadatos del paquete que describen las incompatibilidades del paquete
  2. basado en eso, una herramienta que informa si sus paquetes actuales son compatibles

entonces quizás algunas de las principales diferencias entre MVS y SAT se vuelvan menos importantes.

Gracias por decir eso tan bien Ian. Para continuar, una vez que hayamos establecido las versiones y vgo, definitivamente queremos tener un nuevo godoc.org (tal vez con un nombre diferente) que registre información adicional sobre los paquetes, información que el comando go pueda consultar. Y parte de esa información sería la incompatibilidad de pares que el comando go podría informar como advertencias o errores en cualquier compilación en particular (es decir, informar el daño, no tratar de ocultarlo solucionándolo). Pero tener versiones en la cadena de herramientas central es el primer paso, y eso, junto con los requisitos mínimos de versión y el control de versiones de importación semántica, es lo que se ha aceptado en este número.


Estamos comprometidos a aterrizar esto de la mejor manera posible. Eso requerirá herramientas adicionales, más alcance educativo y relaciones públicas para solucionar problemas en los paquetes existentes. Todo eso quedó bloqueado al aceptar esta propuesta, ya que parecía presuntuoso avanzar sin que se aceptara el planteamiento general. Pero la propuesta es aceptada, y el trabajo empezará a aterrizar con más agresividad ahora que se acabó la incertidumbre.

Pensé lo mismo sobre la información externa para la compatibilidad de la versión... dado que la compatibilidad de la versión debe ser constante, no es necesario que esté en control de fuente (y, de hecho, estar en control de fuente es una clara desventaja como se indicó anteriormente). Sería bueno si hubiera una solución propuesta para esto, ya que definitivamente parece ser el principal problema con MVS como se propone.

Es asombroso ver que la discusión se mueve orgánicamente en esta dirección. Ha sido un eje central de mis preocupaciones, y hace que sea mucho más fácil explicar los problemas fundamentales cuando la gente ya ha recorrido la mayor parte del camino.

@ianlancetaylor , creo que está en lo cierto con esta observación sobre la necesidad de poder realizar cambios en la información de restricción en las versiones ya publicadas. Como indicó @rsc , dicho servicio es algo que hemos discutido/sugerido en nuestras reuniones. Podríamos hacerlo con godoc.org, o algo más, seguro. Pero en realidad no creo que implique un servicio separado, y sería mejor sin uno. Hice una referencia rápida a esto en el artículo que publiqué el viernes (justo arriba de ese ancla). Por lo menos, en un servicio, hay preguntas que deben responderse sobre qué declaración de incompatibilidades debe aparecer en las advertencias, lo que significa manejar la identidad y cómo aplicamos las declaraciones a situaciones particulares en el depgraph. Mantener las declaraciones dentro de los archivos de metadatos significa que no tenemos que preocuparnos por nada de eso. Pero más sobre eso en un segundo.

Lo que es realmente importante aquí es este punto, aunque tal vez no de la forma en que lo pretendías:

quizás algunas de las principales diferencias entre MVS y SAT se vuelven menos importantes.

La sugerencia de una meta-herramienta que hace esta búsqueda, sí, esa es una búsqueda SAT, como una solución a los problemas que la gente está identificando es reveladora. Es más o menos exactamente en lo que tendremos que convertirnos, si MVS sigue adelante como se describe. Y lo primero que hay que tener en cuenta es que, si estamos tan preocupados por estas incompatibilidades que estamos hablando de una herramienta de búsqueda, lo que en realidad estamos diciendo es que MVS se convierte en solo un paso en un algoritmo más grande, y el Los beneficios de grokkability se van por la ventana.

Excepto que es peor que eso, porque ninguna cantidad de metaherramientas puede sortear el problema arraigado de la pérdida de información que surge de la compactación de las versiones mínima y actual. El gran resultado de esto son las reversiones en cascada , lo que significa que intentar remediar cualquiera de las incompatibilidades en esta lista muy probablemente terminará arrojando hacia atrás otras partes del gráfico de dependencia que no necesariamente están relacionadas con su problema. Y los desarrolladores no podrán seguir una estrategia de actualización que no sea dañina para otros. . (Ah, y reglas fantasma , pero eso es solo un efecto secundario de MVS en general).

Es por eso que he afirmado que MVS es una capa intermedia inadecuada sobre la cual construir una herramienta de orden superior como esta: "no es apta para su propósito". Está claro que la gente cree que ocurrirán estas incompatibilidades, por lo que MVS simplemente está tomando un problema difícil y haciéndolo más difícil.

Si, en cambio, unificamos el problema de un "servicio de incompatibilidad" en un archivo de metadatos, entonces creo que es posible , usando solo un conjunto simple de declaraciones por pares, para lograr el mismo efecto. (Este es un borrador del concepto, pero cada vez parece estar más unido)

Implicaría que partes de MVS cambien, pero MVS aún podría ejecutarse sobre la información codificada allí. Eso sería útil en su mayoría si las incompatibilidades realmente se vuelven locas y desea evitarlas todas. Pero el algoritmo principal comenzaría desde una línea de base que se parece a MVS, luego cambiaría a una búsqueda más amplia (para ser claros, MVS en sí mismo aún debería considerarse una búsqueda), sin la posibilidad de pasar a versiones absurdamente antiguas.

(nota, estaré de vacaciones esta semana, así que no responderé hasta el próximo fin de semana)

@sdboyer

La sugerencia de una meta-herramienta que hace esta búsqueda - sí, esa es una búsqueda SAT

¿Puedes ser mas específico? La oración que citó está justo después de que Ian sugiera una herramienta para informar si las versiones seleccionadas son compatibles , y según mi conocimiento, esa es la principal alternativa sugerida aquí (sin duda es lo que pretendía anteriormente). Ese problema definitivamente no es una búsqueda y es trivial y no requiere resolver SAT (solo está evaluando una fórmula booleana para un conjunto dado de valores, no tratando de encontrar valores que la satisfagan).

Correcto, simplemente informar que hay algunos valores incompatibles conocidos en la fórmula no requiere resolver SAT. Tomar cualquier acción sobre esa base, como una herramienta que ayuda en el proceso de encontrar un resultado sin tales valores.

Cité esa oración no porque crea que es indicativo de que las personas hayan aceptado la búsqueda como siempre necesaria, sino porque si creemos que informar esas condiciones es importante, entonces es porque creemos que es probable que nos encontremos con tales escenarios.

el problema es que, una vez que se establece la plausibilidad y la importancia de abordar esos casos, parece que la gente da el salto erróneo de que "podemos hacer todas las cosas de búsqueda además de MVS, y estará bien". podemos, pero tales intentos se vuelven mucho más complicados de manejar debido a los posibles caminos útiles que MVS corta, por diseño.

El 28 de mayo de 2018 a las 4:02:13 p. m. EDT, Axel Wagner [email protected] escribió:

@sdboyer

La sugerencia de una metaherramienta que hace esta búsqueda - sí, esa es una
búsqueda SAT

¿Puedes ser mas específico? La oración que citó está justo después de Ian.
sugiriendo una herramienta para informar si las versiones seleccionadas soncompatible - y que yo sepa, esa es la principal
alternativa sugerida aquí (ciertamente es lo que pretendía anteriormente).
Ese problema definitivamente no es una búsqueda y es trivial y
no requiere resolver SAT (solo está evaluando una fórmula booleana
para un conjunto dado de valores, sin tratar de encontrar valores que lo satisfagan).

--
Estás recibiendo esto porque te mencionaron.
Responda a este correo electrónico directamente o véalo en GitHub:
https://github.com/golang/go/issues/24301#issuecomment-392595150

Cité esa oración no porque crea que es indicativo de que las personas hayan aceptado la búsqueda como siempre necesaria, sino porque si creemos que informar esas condiciones es importante, entonces es porque creemos que es probable que nos encontremos con tales escenarios.

Para ser claros: la sugerencia de adaptar los límites superiores de esta manera es puramente una reacción a las preocupaciones planteadas y para demostrar que se puede hacer (para cuestionar críticamente la afirmación de que MVS es fundamentalmente inadecuado para su propósito). Parece un poco injusto tomar esa concesión y voluntad de compromiso como prueba de que pensamos que tenías razón todo el tiempo.

Para mí, esa afirmación (que MVS no es apto y es un paso esencialmente irreversible en la dirección equivocada) es lo que estoy desafiando personalmente y la lente a través de la cual estoy leyendo sus argumentos. Uno de esos argumentos fue que es una característica si podemos declarar incompatibilidades y hacer que el algoritmo de selección de versión falle cuando se encuentren. Otro argumento justo es que, si ocurren, sería bueno que el algoritmo pudiera resolverlos por nosotros (lo que de hecho requeriría un solucionador SAT).

Sin embargo, si bien creo que esas son preocupaciones válidas y justas, no creo que pasen el listón de demostrarme que MVS es fundamentalmente inadecuado. Todavía creo que MVS como punto de partida trae características buenas e importantes a la mesa. Y que si esas preocupaciones resultan causar un dolor significativo en la práctica, todavía hay muchas maneras en que podemos iterar sobre eso, desde agregar límites superiores (ya sea como parte de go.mod o como un servicio separado) con fallas puras hasta e incluyendo la adición de un solucionador SAT completo y archivos de bloqueo en algún momento. Es decir, estoy de acuerdo contigo en que esas cosas sucederán, pero a) soy (quizás ingenuamente) optimista de que no causarán tanto dolor como anticipas yb) que son problemas solucionables incluso cuando empezamos con MVS.

Se me ocurre que algo fuera del control de fuente que determina la compatibilidad cambiaría el determinismo de un sistema MVS. Si tiene foo >= 1.5.0 como restricción en una biblioteca y otra biblioteca tiene foo >= 1.6.0. Luego ponga esos dos en un binario y eligen 1.6.0. En MVS, esto es todo lo que necesita para una compilación repetible. siempre elegirá 1.6

Pero si agrega compatibilidad externa a la mezcla, entonces podría actualizar esa primera biblioteca para decir que no es compatible con 1.6, y luego el algoritmo elegiría 1.7, aunque el código no haya cambiado... Lo que significa que necesitaría un archivo de bloqueo de nuevo.

Como referencia, no creo que un archivo de bloqueo sea algo malo. Es bueno tener una lista explícita de exactamente lo que necesita construir. Y eso debería hacerlo rápido. No se necesita lógica mágica.

@natefinch Si el archivo go.mod de la aplicación se actualizó para requerir v1.7.0 porque la herramienta de compatibilidad externa indicó que v1.6.0 era incompatible, no necesitaría un archivo de bloqueo. Debido a que la especificación de v1.7.0 se encuentra en el archivo go.mod, el autor también podría agregar un comentario diciendo por qué se usa v1.7.0 y esa información sería útil para los lectores.

@leighmcculloch , si se actualiza algún archivo en la aplicación, entonces es una compilación diferente y está totalmente fuera del alcance del problema de "compilación reproducible sin archivo de bloqueo".

Se propone información de compatibilidad fuera de banda para reflejar cómo se desarrolla el conocimiento: no se conocían incompatibilidades en el momento del lanzamiento, pero luego se hicieron evidentes y se publica información adicional sobre las versiones ya lanzadas. En mi humilde opinión, por definición, este enfoque conduce a un cambio en la forma en que se extraen las dependencias, de lo contrario, ¿por qué tener esta información de incompatibilidad de extracción?

@redbaron @natefinch

El objetivo de la información de incompatibilidad es que los autores de las bibliotecas comuniquen la información de incompatibilidad a sus usuarios. Si esa información se usa en el momento de la compilación o en el momento del lanzamiento es una cuestión diferente.

En el caso de vgo, la idea actual es mostrar solo advertencias (o potencialmente croar). Pero, en particular, para no dejar que influya en la elección de las versiones utilizadas (ya que eso requeriría resolver el SAT). Así que en realidad no importa, puede usarlo en cualquiera de los dos o en ambos y cumplirá perfectamente con su deber, conservando la propiedad de repetibilidad¹.

En dep, esta información solo se usa en el momento del lanzamiento y luego se registra en un archivo de bloqueo, que se usa en el momento de la compilación. Así que parece que estamos considerando un uso de tiempo de lanzamiento "suficientemente bueno" de todos modos, al menos cuando se trata de preocupaciones de vgo vs. dep.

Sin embargo, todavía no creo que tengamos que responder esas preguntas en este momento.


[1] Personalmente, diría que usarlo en el momento del lanzamiento y solo si se usa -v en el momento de la compilación es mejor, porque un usuario no debería tener que decidir si una advertencia es accionable o no.

@rsc escribió:

Para continuar, una vez que hayamos establecido las versiones y vgo, definitivamente queremos tener un nuevo godoc.org (tal vez con un nombre diferente) que registre información adicional sobre los paquetes, información que el comando go pueda consultar. Y parte de esa información sería la incompatibilidad de pares que el comando go podría informar como advertencias o errores en cualquier compilación en particular (es decir, informar el daño, no tratar de ocultarlo solucionándolo).

Me pregunto si es necesario registrar la incompatibilidad de pares. La forma en que lo veo actualmente es que cualquier incompatibilidad entre el módulo A@vN y el módulo B@vM es realmente porque B hizo un cambio incompatible de alguna versión vL donde L <M.

Si el módulo B no hizo un cambio incompatible, entonces el módulo A solo tiene un error. Si lo hizo, entonces el problema es sobre B en sí mismo, no sobre el emparejamiento de A y B.

Entonces ISTM que cualquier depósito público de metadatos de módulos puede registrar solo incompatibilidades de cualquier módulo con versiones anteriores de sí mismo, lo que puede hacer que el problema sea más manejable. Estos informes de incompatibilidad son bastante similares a los informes de errores, aunque no se pueden resolver porque una vez que se publica una versión, no se puede cambiar.

Cuando actualiza las versiones de su módulo, la herramienta go podría considerar los metadatos y negarse a considerar una versión que sea incompatible con cualquier versión elegida actualmente. Creo que esto evita la necesidad de resolver SAT. También podría decidir que un módulo determinado tiene demasiados informes de incompatibilidad y negarse a agregarlo como dependencia.

Un conjunto de tuplas de la forma ( module , oldVersion , newVersion , description ) podría ser suficiente.

la herramienta go podría considerar los metadatos y negarse a considerar una versión que sea incompatible con cualquier versión elegida actualmente

Por supuesto, esto no funciona cuando agrega varias dependencias, que entre ellas terminan requiriendo el uso de versiones mutuamente incompatibles, porque las nuevas versiones no son parte del módulo existente, pero puede haber una heurística razonable disponible. No es AFAICS crucial, porque las dependencias deben agregarse relativamente raramente.

Me preocupa que go release se esté convirtiendo en el "compilador suficientemente inteligente" de esta discusión. ¿Qué pueden esperar concretamente los usuarios de go release en Go 1.11/12? Creo que eso marca la diferencia en cuanto a las expectativas razonables en torno a MVS/SIV.

Gracias por la energía que tantos de vosotros habéis aportado a Go ya esta propuesta en particular.

El primer objetivo del proceso de propuesta es "[a]segurarse de que las propuestas obtengan una evaluación registrada adecuada, justa, oportuna y con una respuesta clara". Esta propuesta fue discutida extensamente y publicamos un resumen de la discusión. Después de seis semanas y mucha discusión, el comité de revisión de propuestas, interviniendo como árbitro porque yo escribí la propuesta, aceptó la propuesta.

Un solo problema de GitHub es un lugar difícil para tener una discusión amplia, porque GitHub no tiene subprocesos para diferentes hilos de la conversación y ya ni siquiera muestra todos los comentarios. La única forma en que una discusión como esta funciona es mediante la curación activa del resumen de la discusión. Incluso el resumen se había vuelto difícil de manejar cuando se aceptó la propuesta.

Ahora que se acepta la propuesta, este tema ya no es el lugar adecuado para la discusión y ya no estamos actualizando el resumen. En su lugar, envíe problemas nuevos y específicos sobre los problemas que tiene o sugerencias concretas para cambios, de modo que podamos tener discusiones enfocadas sobre cada tema específico. Prefije estos nuevos problemas con "x/vgo:". Si menciona #24301 en el texto de la nueva edición, se hará una referencia cruzada aquí para que otros lo encuentren.

Un último punto es que aceptar la propuesta significa aceptar la idea, no los errores de implementación del prototipo y todo. Todavía hay detalles por resolver y errores por corregir, y continuaremos haciéndolo juntos.

Gracias, de nuevo, por toda su ayuda.

Hay más trabajo por hacer (consulte la etiqueta de los módulos ), pero la implementación del módulo inicial, tal como se propone en este problema, se ha comprometido con el árbol principal, por lo que estoy cerrando este problema.

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