Après le passage d’un réseau mobile, d’un Wi-Fi d’entreprise ou d’un environnement de test opérateur en IPv6-only, les incidents les plus fréquents ne prennent pas la forme d’une « coupure totale ». L’utilisateur peut se connecter, mais l’envoi d’images échoue ; la première requête aboutit, mais la reconnexion expire ; ou une ancienne interface utilise encore une adresse IPv4 codée en dur dans sa configuration. Un Mac cloud permet de transformer ces problèmes intermittents en contrôles systématiques : chaque fusion déclenche une recherche des adresses littérales, une vérification des conditions de résolution DNS64, l’exécution des tests réseau et l’archivage des éléments de diagnostic en cas d’échec.
Définir d’abord le périmètre du contrôle
La compatibilité IPv6-only ne signifie pas que le serveur doit exclusivement publier des enregistrements AAAA. Si le réseau de test dispose de DNS64/NAT64, un client qui utilise un nom de domaine et confie sa résolution au résolveur système peut toujours accéder à un service disponible uniquement en IPv4. Le véritable risque apparaît lorsque le client contourne le mécanisme de résolution du système, par exemple en mettant en cache une adresse IPv4 déjà résolue, en imposant AF_INET ou en inscrivant une adresse telle que 192.0.2.10 dans la configuration métier.
Il est recommandé d’organiser le contrôle en trois niveaux :
| Niveau | Éléments contrôlés | Éléments conservés en cas d’échec |
|---|---|---|
| Analyse statique | Adresses IPv4 littérales, constantes de famille d’adresses, sockets créés manuellement | Nom de fichier et numéro de ligne |
| Vérification préalable de l’environnement | DNS, route par défaut, résolution du domaine cible | Résultats de scutil et de la résolution |
| Tests fonctionnels | Connexion, envoi, nouvelle tentative, reprise des connexions persistantes | Journaux de test et paquet de résultats |
Ne considérez pas un
pingréussi comme une validation fonctionnelle. L’application utilise réellement HTTPS, WebSocket ou l’envoi de fichiers ; le chemin des requêtes, la stratégie de délai d’attente et la réutilisation des connexions peuvent produire des résultats différents.
Rechercher les hypothèses IPv4 dans le dépôt
Commencez par effectuer une recherche prudente dans l’espace de travail CI. L’expression ci-dessous sert uniquement à repérer des éléments potentiellement problématiques. Tous les résultats ne doivent pas être considérés automatiquement comme des défauts, car les fixtures de test, la documentation et les adresses de bouclage peuvent être légitimes.
set -euo pipefail
mkdir -p artifacts/ipv6
rg -n \
--glob '*.{swift,m,mm,h,plist,json,yaml,yml,xcconfig}' \
'([0-9]{1,3}\.){3}[0-9]{1,3}|AF_INET([^6]|$)|sockaddr_in([^6]|$)' \
. | tee artifacts/ipv6/ipv4-candidates.txt
if rg -n \
--glob 'Sources/**' \
--glob 'Config/**' \
'https?://([0-9]{1,3}\.){3}[0-9]{1,3}' .; then
echo "Production configuration contains an IPv4 URL" >&2
exit 1
fi
La liste des résultats doit faire l’objet d’un premier classement manuel. Placez ensuite les exceptions autorisées dans une liste blanche documentée. N’excluez pas directement tout le répertoire Tests, car le code utilitaire des tests peut lui aussi être recopié dans la couche réseau de production. Pour les wrappers C ou Objective-C, vérifiez en priorité que le champ ai_family de getaddrinfo utilise AF_UNSPEC. Il ne doit être fixé que lorsqu’une seule famille d’adresses est explicitement requise.
Éviter les corrections erronées
Ne convertissez pas mécaniquement une adresse IPv4 en adresse IPv6 mappée, et ne construisez pas vous-même un préfixe NAT64. Ce préfixe dépend du réseau actif ; s’il est codé en dur, il cessera de fonctionner dès que le réseau changera. La bonne approche consiste à conserver le nom de domaine et à laisser le résolveur système fournir les adresses disponibles au moment d’établir la connexion.
Vérifier les conditions DNS64 avant les tests
Enregistrez l’état du réseau avant de commencer les tests afin d’éviter une série de faux positifs lorsque l’environnement ne remplit pas les conditions nécessaires. Les nœuds d’exécution du Mac cloud doivent utiliser un réseau DNS64/NAT64 contrôlé et préparé par l’équipe. Le script CI doit uniquement vérifier ces conditions, sans modifier temporairement la configuration réseau du système pendant la tâche.
set -euo pipefail
OUT="artifacts/ipv6"
mkdir -p "$OUT"
scutil --dns > "$OUT/scutil-dns.txt"
route -n get default > "$OUT/default-route.txt" 2>&1 || true
dscacheutil -q host -a name api.test.example \
> "$OUT/target-resolution.txt"
if ! grep -Eq 'ipv6_address|ip_address' "$OUT/target-resolution.txt"; then
echo "Target hostname did not resolve in the test environment" >&2
exit 2
fi
Le domaine de test doit appartenir à un environnement contrôlé par l’équipe et renvoyer une réponse de vérification d’état stable, sans informations sensibles. N’utilisez pas une page web publique comme dépendance du contrôle : une limitation externe, une modification de certificat ou une politique régionale rendrait les résultats de build non déterministes.
Vérifier le comportement réel avec URLSession
Les tests réseau doivent couvrir deux scénarios : la réussite de la première tentative et la reprise après un échec. Les requêtes doivent définir des délais d’attente finis, et l’URL de base doit être fournie par injection de dépendances afin d’éviter qu’une adresse soit de nouveau codée en dur dans les tests.
import XCTest
final class IPv6ReadinessTests: XCTestCase {
func testHealthEndpointReturnsExpectedStatus() async throws {
let value = try XCTUnwrap(
ProcessInfo.processInfo.environment["TEST_BASE_URL"]
)
let baseURL = try XCTUnwrap(URL(string: value))
let url = baseURL.appending(path: "health")
let configuration = URLSessionConfiguration.ephemeral
configuration.timeoutIntervalForRequest = 15
configuration.timeoutIntervalForResource = 30
let session = URLSession(configuration: configuration)
let (_, response) = try await session.data(from: url)
let http = try XCTUnwrap(response as? HTTPURLResponse)
XCTAssertEqual(http.statusCode, 200)
}
}
Lors de l’exécution, fixez le plan de test, le modèle de simulateur et le répertoire des résultats :
set -o pipefail
xcodebuild test \
-workspace App.xcworkspace \
-scheme AppNetworkTests \
-testPlan IPv6Readiness \
-destination 'platform=iOS Simulator,name=iPhone 16' \
-resultBundlePath artifacts/ipv6/IPv6Readiness.xcresult \
TEST_BASE_URL='https://api.test.example/' \
| tee artifacts/ipv6/xcodebuild.log
Si l’application gère l’envoi de fichiers et les connexions persistantes, ajoutez également des tests pour l’envoi d’un petit fichier, le backoff exponentiel après une interruption de connexion et la reprise après un passage entre le premier plan et l’arrière-plan. Les assertions doivent porter sur les résultats fonctionnels et non dépendre de messages d’erreur localisés.
Conserver des éléments exploitables en cas d’échec
En cas d’échec du contrôle, conservez au minimum les résultats de l’analyse statique, l’état DNS, les résultats de résolution de la cible, le journal xcodebuild et le fichier xcresult. Les journaux ne doivent contenir ni jetons, ni corps de requête, ni en-têtes d’autorisation complets. Si des informations sur les requêtes doivent être consignées, limitez-les à la méthode, au chemin expurgé, au code d’état, au nombre de nouvelles tentatives et au domaine d’erreur.
La procédure de diagnostic peut être standardisée comme suit :
- Vérifiez que les contrôles préalables de l’environnement ont réussi et que le domaine cible a été résolu par le système.
- Vérifiez que la requête en échec utilise un nom de domaine, et non une adresse mise en cache après résolution.
- Vérifiez que la bibliothèque bas niveau n’impose pas
AF_INETet ne crée pas elle-même un socket IPv4. - Comparez les chemins de première connexion et de reconnexion pour confirmer qu’ils appliquent la même stratégie de résolution.
- Reproduisez les parcours critiques sur un appareil physique connecté au réseau DNS64/NAT64 contrôlé.
Le contrôle sur simulateur assure les régressions fréquentes, tandis que l’appareil physique sert à la validation avant publication. En séparant ces responsabilités, les builds courants ne dépendent plus d’opérations manuelles, et l’équipe réseau peut déterminer à partir des éléments archivés si le problème se situe au niveau de la résolution, de la connexion ou de la logique métier de nouvelle tentative. Sur VPSGit, il suffit de maintenir la même chaîne d’outils, le même plan de test et les mêmes variables d’environnement sur les nœuds d’exécution pour répéter durablement ces contrôles, au lieu de recréer l’environnement en urgence après le signalement d’un utilisateur.
Questions fréquentes
L’utilisation de noms de domaine garantit-elle la compatibilité IPv6-only ?
Non. Le service doit rester accessible via DNS64/NAT64 et l’application ne doit ni mémoriser une adresse IPv4, ni imposer AF_INET, ni contourner le résolveur système.
Les tests dans le simulateur iOS sont-ils suffisants ?
Ils conviennent à la régression continue, mais une validation finale sur appareil dans un réseau DNS64/NAT64 contrôlé reste nécessaire pour la connexion, les transferts et la reprise des sessions.
Configurez un Mac cloud pour votre prochain build ou votre prochaine tâche d’inférence
Choisissez parmi trois configurations Apple Silicon, six nœuds et des durées de location fixes. La disponibilité réelle est indiquée en temps réel dans la console.