Black Friday dans 15 jours : vos clients pourront-ils payer ? -25 % la 1re année et mise en place offerte, jusqu’au 30 novembreVoir l’offre →

Intégration

Tester le tunnel de paiement à chaque déploiement avec GitHub Actions

Après chaque mise en production, un vrai navigateur refait le chemin du client jusqu’à la page de paiement. Si une étape casse, le job passe au rouge.

Obtenir ma clé d’APIContrat OpenAPI

Document complet, sans authentification, à donner à votre générateur de client.

Le workflow complet, à copier

Voici le fichier entier. Le job deploy met votre site en production. Le job tunnel-paiement demande ensuite à Pathly de rejouer votre Flow dans un vrai navigateur, du produit jusqu’à la page de paiement. Si une étape casse, le job passe au rouge.

La ligne needs: deploy fixe l’ordre. Le job tunnel-paiement ne démarre que si le déploiement a réussi. Le Flow teste donc la version qui vient d’arriver en production, pas la précédente.

timeout_sec donne à l’Action le temps d’attendre le verdict. Sa valeur par défaut est de 120 secondes. Un tunnel de paiement compte plusieurs pages : le workflow laisse cinq minutes. Passé ce délai, l’Action s’arrête et le job échoue.

Il vous reste trois choses à préparer : le Flow, la clé d’API et les deux réglages du dépôt. Les sections suivantes les détaillent dans cet ordre.

# .github/workflows/deploy.yml
name: Deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # Remplacez par votre commande de déploiement
      - run: ./scripts/deploy.sh

  tunnel-paiement:
    name: Tunnel de paiement
    needs: deploy
    runs-on: ubuntu-latest
    steps:
      - name: Pathly Flow
        uses: pathlyhq/pathly-action@v1
        with:
          api_token: ${{ secrets.PATHLY_API_TOKEN }}
          operation: run-scenario
          scenario_id: ${{ vars.PATHLY_CHECKOUT_SCENARIO_ID }}
          timeout_sec: "300"

Pourquoi tester après la mise en production

Vos tests avant fusion vérifient le code. Ils ne voient pas la production : ses variables d’environnement, son cache, son prestataire de paiement, ses scripts tiers. Une mise en production peut casser le tunnel de paiement alors que tous les tests sont verts.

Le cas type : le Ping est vert, le Flow est rouge. Le site répond 200 et la page d’accueil s’affiche, mais le bouton Commander ne fait plus rien. Un contrôle de disponibilité ne le voit pas. Un navigateur qui clique, si.

Ce contrôle ne remplace pas vos tests avant fusion. Il s’ajoute après eux. Les tests disent que le code est correct. Le Flow dit qu’un client peut encore atteindre la page de paiement, sur le vrai site, quelques minutes après le déploiement.

Créer le Flow du tunnel de paiement

Le Flow se crée dans la console, avec l’enregistreur, sans écrire de code. Vous ouvrez votre boutique dans l’enregistreur et vous faites le chemin d’un client. Pathly garde chaque clic comme une étape.

Étapes types : ouvrir une fiche produit, ajouter le produit au panier, ouvrir le panier, continuer jusqu’à la page de paiement. Ajoutez une vérification à la fin, par exemple un texte que seule la page de paiement affiche.

Le Flow s’arrête à la page de paiement. Il ne paie rien et ne saisit que des valeurs de test. Choisissez un produit toujours disponible, réservé à ce contrôle si vous le pouvez.

Une fois le Flow enregistré, relevez son identifiant. C’est un UUID, visible dans l’adresse de la page du Flow dans la console. Vous le rangerez dans une variable du dépôt à l’étape suivante.

Une clé d’API à deux portées

Créez une clé d’API dans la console, sous Réglages → Clés d’API. Elle commence par sp_… et son secret ne s’affiche qu’une fois. Donnez-lui deux portées seulement : runs:trigger pour lancer un run, runs:read pour lire son résultat.

Créez une clé par dépôt. Si un dépôt fuit, vous révoquez sa clé sans toucher aux autres. Avec ces deux portées, une clé volée ne peut ni créer, ni modifier, ni supprimer un Flow.

Dans GitHub, ouvrez Settings → Secrets and variables → Actions. Rangez la clé dans le secret PATHLY_API_TOKEN. Rangez l’identifiant du Flow dans la variable PATHLY_CHECKOUT_SCENARIO_ID. L’identifiant n’est pas un secret : une variable suffit, et elle reste lisible dans les journaux.

Avant de brancher le Flow, faites un premier contrôle avec operation: ping. Cette opération vérifie seulement que l’API reconnaît la clé. Elle ne lance aucun run.

Premier contrôle : la clé est reconnue

- name: Pathly ping
  uses: pathlyhq/pathly-action@v1
  with:
    api_token: ${{ secrets.PATHLY_API_TOKEN }}
    operation: ping

run-scenario ou assert-scenario

L’Action propose deux opérations qui se ressemblent. Après un déploiement, c’est run-scenario qu’il vous faut. Elle lance un nouveau run par POST /v1/scenarios/{id}/run, puis interroge GET /v1/runs/{id} jusqu’à un statut final. Le résultat décrit donc la version que vous venez de livrer.

assert-scenario ne lance rien. Elle lit le dernier résultat connu du Flow, avec la portée scenarios:read. Ce résultat peut dater d’avant le déploiement : le job serait vert alors que la nouvelle version n’a jamais été testée.

assert-scenario garde un intérêt ailleurs. Elle ne consomme aucune exécution et répond tout de suite. Elle convient à un contrôle avant une étape risquée, quand le Flow tourne déjà à intervalle régulier. Elle ne convient pas juste après une mise en production.

assert-scenario : lit le dernier résultat, ne lance rien

- name: Pathly assert
  uses: pathlyhq/pathly-action@v1
  with:
    api_token: ${{ secrets.PATHLY_API_TOKEN }}
    operation: assert-scenario
    scenario_id: ${{ vars.PATHLY_CHECKOUT_SCENARIO_ID }}

Lire un échec

L’Action déclare trois sorties : run_id, run_status et ok. run_status vaut ok, fail ou error. Quand le run n’est pas ok, le job échoue. Son journal affiche alors l’identifiant du run, son statut et son message : partez de là.

fail : une étape ou une vérification du Flow échoue. Le site répond, mais le chemin du client est cassé. C’est le cas que ce contrôle doit attraper : un bouton qui ne réagit plus, un panier vide, une page de paiement jamais atteinte.

error : le run n’est pas allé au bout à cause d’une erreur de réseau ou du navigateur. Site injoignable, délai de connexion dépassé, navigateur planté. Un site qui ne répond plus du tout après la mise en production donne donc error, pas fail.

Pour le détail, appelez GET https://api.pathlyhq.com/v1/runs/{id} avec la même clé. La réponse rend status, message et, quand une capture existe, screenshotUrl. C’est un lien signé vers la capture de l’étape en échec, valable 15 minutes. screenshotExpiresAt donne l’heure de fin de validité. Rappelez la route pour obtenir un nouveau lien.

Le détail d’un run et le lien de sa capture

# RUN_ID : l'identifiant affiché dans le journal du job
curl -sS https://api.pathlyhq.com/v1/runs/$RUN_ID \
  -H "Authorization: Bearer $PATHLY_API_TOKEN" \
  | jq '{status, message, screenshotUrl, screenshotExpiresAt}'

Le dernier run du Flow, sans connaître son identifiant

curl -sS "https://api.pathlyhq.com/v1/runs?scenarioId=$PATHLY_CHECKOUT_SCENARIO_ID&limit=1" \
  -H "Authorization: Bearer $PATHLY_API_TOKEN" \
  | jq '.items[0] | {id, status, message}'

Réagir : retour arrière et alerte

Un job rouge ne sert à rien si personne ne le regarde. Ajoutez un job rollback avec needs: tunnel-paiement et if: failure(). Il ne tourne que si le contrôle a échoué, et il remet la version précédente en production.

failure() est vraie dès qu’un job en amont échoue, le déploiement compris. La condition needs.tunnel-paiement.result == 'failure' réserve le retour arrière au seul échec du contrôle Pathly.

Le job est rouge sur fail comme sur error, mais la réponse diffère. Sur fail, le chemin du client est cassé : revenez en arrière. Sur error, relancez le job une fois. Si l’erreur revient, revenez en arrière aussi.

Prévenez aussi l’équipe. Un webhook abonné à l’événement run.failed pousse l’échec vers votre outil d’alerte. Créez-le dans la console, ou par l’API avec une clé qui porte alerting:write, distincte de celle de la CI. Les canaux tiers (Slack, Teams, webhooks) font partie des offres payantes.

Job rollback, à la suite des deux autres

  rollback:
    needs: tunnel-paiement
    if: failure() && needs.tunnel-paiement.result == 'failure'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # Remplacez par votre commande de retour arrière
      - run: ./scripts/rollback.sh

Webhook run.failed vers votre outil d’alerte

# PATHLY_ALERTING_TOKEN : une clé avec alerting:write, pas celle de la CI
curl -sS -X POST https://api.pathlyhq.com/v1/webhooks \
  -H "Authorization: Bearer $PATHLY_ALERTING_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://www.example.com/hooks/pathly",
    "events": ["run.failed"]
  }'

Aller plus loin

Plusieurs boutiques : créez un Flow par boutique et parcourez leurs identifiants avec strategy.matrix. Chaque boutique a son job et son verdict. Avec fail-fast: false, l’échec d’une boutique n’annule pas le contrôle des autres.

Fenêtre de maintenance : si le déploiement coupe le site un instant, ouvrez une fenêtre avant de déployer. Elle fait taire les alertes de la surveillance régulière pendant le créneau. L’Action n’a pas d’opération dédiée : appelez l’API /v1/maintenance-windows avec une autre clé, qui porte maintenance:write.

ensure-scenario crée le Ping du site s’il n’existe pas. S’il existe déjà, elle le laisse tel quel, sans le modifier. Elle le retrouve par son nom : relancer le workflow ne crée pas de doublon. Cette opération demande la portée scenarios:write, donc une clé distincte de celle du contrôle.

Deux déploiements à la suite : sans garde, deux contrôles se croisent et le second peut tester une version à moitié livrée. Un bloc concurrency fait attendre la seconde exécution du workflow jusqu’à la fin de la première, contrôle compris.

Plusieurs boutiques avec strategy.matrix

  tunnel-paiement:
    needs: deploy
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        scenario_id:
          - ${{ vars.PATHLY_CHECKOUT_FR_SCENARIO_ID }}
          - ${{ vars.PATHLY_CHECKOUT_DE_SCENARIO_ID }}
    steps:
      - name: Pathly Flow
        uses: pathlyhq/pathly-action@v1
        with:
          api_token: ${{ secrets.PATHLY_API_TOKEN }}
          operation: run-scenario
          scenario_id: ${{ matrix.scenario_id }}
          timeout_sec: "300"

Fenêtre de maintenance de quinze minutes, avant le déploiement

START=$(date -u +%Y-%m-%dT%H:%M:%SZ)
END=$(date -u -d "+15 minutes" +%Y-%m-%dT%H:%M:%SZ)

curl -sS -X POST https://api.pathlyhq.com/v1/maintenance-windows \
  -H "Authorization: Bearer $PATHLY_MAINTENANCE_TOKEN" \
  -H "Content-Type: application/json" \
  -d "{\"startsAt\": \"$START\", \"endsAt\": \"$END\"}"

ensure-scenario : le Ping du site, sans doublon

- name: Pathly Ping
  uses: pathlyhq/pathly-action@v1
  with:
    api_token: ${{ secrets.PATHLY_SETUP_TOKEN }}
    operation: ensure-scenario
    scenario_json: |
      {
        "name": "Home",
        "url": "https://www.example.com/",
        "intervalSec": 300
      }

concurrency : un déploiement à la fois

concurrency:
  group: deploy-production
  cancel-in-progress: false

Pièges courants

Le CDN sert encore l’ancienne version. Le Flow teste alors le site d’avant et le job est vert à tort. Purgez le cache dans le job deploy et attendez la fin de la purge avant de laisser la main au contrôle.

Une protection anti-robot ou un CAPTCHA bloque le navigateur de Pathly. Le Flow échoue alors que vos clients passent. Un CAPTCHA arrête ce navigateur comme n’importe quel robot : gardez-le hors des pages que le Flow traverse, ou prévoyez une règle pour ce trafic de test dans votre pare-feu applicatif.

Le produit de test est en rupture de stock. Le bouton d’ajout au panier disparaît et le Flow passe au rouge sans que le code ait changé. Réservez au test un produit toujours disponible.

Le quota. Un run lancé par la CI compte dans le quota d’exécutions de votre offre, comme les autres. Quota atteint sans pack d’exécutions, le run finit en fail avec un message de quota et le job passe au rouge. Lisez le message avant de revenir en arrière : ici, le site n’y est pour rien.