Contexte et problème de couplage
Dans l’écosystème Go, l’adresse d’importation inclut le nom d’hôte du dépôt. Un import tel que import "github.com/thetrueares/boneclone" indique à l’outil go get de récupérer le code depuis GitHub via Git. Cette convention simplifie le repérage des bugs et la distribution, mais crée une dépendance directe au fournisseur d’hébergement. Si le dépôt migre vers GitLab ou Azure DevOps, chaque fichier source doit être modifié pour refléter le nouveau domaine, sous peine de récupérer une version obsolète. L’article cite un cas d’entreprise qui a maintenu simultanément GitHub, GitLab et Azure DevOps, entraînant des coûts supplémentaires liés à la gestion de trois services d’hébergement.
Mécanisme d’import Go et métadonnées
L’outil Go interroge l’URL d’importation avec le paramètre ?go-get=1. Le serveur doit répondre avec des balises <meta name="go-import"> et <meta name="go-source"> décrivant le protocole VCS et l’emplacement du code source. Sans ces balises, go get ne peut pas résoudre le dépôt. Le même serveur peut, en revanche, servir du HTML classique aux visiteurs humains, ce qui nécessite une logique de redirection conditionnelle.
Solution par domaine personnalisé
Le contournement consiste à placer un domaine dédié (ex. go.iain.rocks) devant le dépôt. Le DNS du domaine pointe vers un serveur web qui, selon la présence du paramètre go-get=1, renvoie soit les métadonnées, soit une redirection vers le dépôt réel. Ainsi, le chemin d’importation go.iain.rocks/boneclone reste stable même si le code migre de GitHub à GitLab ; il suffit de mettre à jour la configuration du serveur, pas le code Go.
server {
server_name go.iain.rocks;
root /var/www/go.iain.rocks;
index index.html;
location / {
if ($args !~ go-get=1) {
return 301 https://github.com/that-guy-iain$request_uri;
}
try_files $uri $uri/ =404;
}
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/go.iain.rocks/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/go.iain.rocks/privkey.pem;
}
server {
listen 80;
server_name go.iain.rocks;
return 301 https://$host$request_uri;
}Le fichier index.html contient les balises attendues par le client Go :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="go-import" content="go.iain.rocks/boneclone git https://github.com/that-guy-iain/boneclone">
<meta name="go-source" content="go.iain.rocks/boneclone https://github.com/that-guy-iain/boneclone https://github.com/that-guy-iain/boneclone/tree/master{/dir} https://github.com/that-guy-iain/boneclone/blob/master{/dir}/{file}#L{line}">
</head>
<body></body>
</html>Mise en œuvre et limites
Déployer la solution requiert un serveur HTTP (Nginx ou équivalent), un certificat TLS et la configuration DNS du domaine. Le coût opérationnel est limité à la gestion du serveur et du certificat, bien inférieur aux frais de plusieurs services d’hébergement. La principale contrainte réside dans la disponibilité du serveur : une panne empêche l’accès aux métadonnées et bloque go get. En outre, la redirection vers le dépôt d’origine doit rester à jour, sinon les développeurs récupèrent du code non maintenu. Malgré ces exigences, le modèle offre une flexibilité de migration sans toucher le code source Go.