Architecture du pipeline

Universal Installer V2 expose une API REST FastAPI qui permet d'intégrer toutes ses fonctions dans n'importe quel pipeline CI/CD. Le serveur tourne sur un runner GitLab dédié et reçoit les commandes de compression, packaging et déploiement depuis le pipeline.

# Architecture du pipeline
Code commit
  └── GitLab CI trigger
        ├── Stage 1 : build (PyInstaller)
        ├── Stage 2 : compress + package (Universal Installer API)
        ├── Stage 3 : sign (SignTool / GPG)
        ├── Stage 4 : deploy cloud (Universal Installer API)
        └── Stage 5 : notify (Slack / email)

L'API REST d'Universal Installer

Le serveur API démarre en une commande et expose un Swagger UI pour tester les endpoints :

# Démarrer le serveur API
universal-installer api   --port 8420   --host 0.0.0.0   --auth-token $UI_API_TOKEN   --work-dir /tmp/ui-workspace

# Swagger UI disponible à http://runner:8420/docs

Les stages GitLab CI

# .gitlab-ci.yml
stages:
  - build
  - package
  - sign
  - deploy
  - notify

variables:
  UI_API: "http://ui-runner:8420"
  UI_TOKEN: $UI_API_TOKEN  # Variable CI/CD secrète GitLab

Stage : compression et packaging

package:
  stage: package
  tags: [ui-runner]
  script:
    - |
      # Compresser le dossier de build
      RESPONSE=$(curl -s -X POST "$UI_API/api/v1/compress"         -H "Authorization: Bearer $UI_TOKEN"         -H "Content-Type: application/json"         -d '{
          "source": "dist/",
          "output": "artifacts/app_'"$CI_COMMIT_TAG"'.uxc",
          "algo": "auto",
          "encrypt": true,
          "encrypt_password": "'"$ARCHIVE_PASSWORD"'"
        }')

      echo "Compression: $RESPONSE"
      RATIO=$(echo $RESPONSE | python3 -c "import sys,json; print(json.load(sys.stdin)['ratio'])")
      echo "Ratio: $RATIO"

    - |
      # Générer le patch delta depuis la version précédente
      curl -s -X POST "$UI_API/api/v1/delta"         -H "Authorization: Bearer $UI_TOKEN"         -H "Content-Type: application/json"         -d '{
          "source": "releases/app_latest.uxc",
          "target": "artifacts/app_'"$CI_COMMIT_TAG"'.uxc",
          "output": "artifacts/patch_'"$CI_COMMIT_TAG"'.uxcd"
        }'

  artifacts:
    paths: [artifacts/]
    expire_in: 30 days

Stage : signature et vérification

sign:
  stage: sign
  tags: [windows-runner]  # SignTool requiert Windows
  script:
    - # Générer MSI depuis l'archive UXC
    - |
      curl -s -X POST "$UI_API/api/v1/make-installer"         -H "Authorization: Bearer $UI_TOKEN"         -d '{"source": "artifacts/app_'"$CI_COMMIT_TAG"'.uxc",
             "type": "msi", "version": "'"$CI_COMMIT_TAG"'"}'

    - # Signer avec Authenticode
    - signtool sign /tr http://timestamp.digicert.com /td sha256 /fd sha256
        /f %CERT_PATH% /p %CERT_PASSWORD%
        artifacts/*.msi

    - # Vérifier l'intégrité
    - |
      curl -s -X POST "$UI_API/api/v1/verify"         -H "Authorization: Bearer $UI_TOKEN"         -d '{"path": "artifacts/app_'"$CI_COMMIT_TAG"'.uxc"}'

Stage : déploiement cloud

deploy:
  stage: deploy
  tags: [ui-runner]
  only: [tags]
  script:
    - |
      RESULT=$(curl -s -X POST "$UI_API/api/v1/upload"         -H "Authorization: Bearer $UI_TOKEN"         -H "Content-Type: application/json"         -d '{
          "local_path": "artifacts/app_'"$CI_COMMIT_TAG"'.uxc",
          "profile": "prod-s3",
          "remote_path": "releases/app_'"$CI_COMMIT_TAG"'.uxc",
          "also_upload_delta": true,
          "delta_path": "artifacts/patch_'"$CI_COMMIT_TAG"'.uxcd",
          "update_latest": true
        }')

      URL=$(echo $RESULT | python3 -c "import sys,json; print(json.load(sys.stdin)['url'])")
      echo "Déployé : $URL"
      echo "RELEASE_URL=$URL" >> deploy.env

  artifacts:
    reports:
      dotenv: deploy.env

Rollback sur échec

rollback:
  stage: deploy
  tags: [ui-runner]
  when: on_failure
  script:
    - |
      # Restaurer la version précédente
      curl -s -X POST "$UI_API/api/v1/rollback"         -H "Authorization: Bearer $UI_TOKEN"         -d '{
          "profile": "prod-s3",
          "remote_path": "releases/app_latest.uxc",
          "rollback_to": "releases/app_'"$CI_COMMIT_BEFORE_SHA"'.uxc"
        }'

Notifications

notify:
  stage: notify
  when: always
  script:
    - |
      STATUS="succès"
      if [ "$CI_JOB_STATUS" = "failed" ]; then STATUS="échec"; fi
      curl -X POST "$SLACK_WEBHOOK"         -d '{"text": "'"$CI_PROJECT_NAME"' v'"$CI_COMMIT_TAG"' : '"$STATUS"'
URL: '"$RELEASE_URL"'"}'

Conclusion

L'API REST de Universal Installer V2 transforme chaque fonctionnalité (compression, packaging, signature, déploiement cloud, delta) en un endpoint REST appelable depuis n'importe quel pipeline CI/CD. Le pipeline GitLab CI décrit ici est reproductible et couvre tout le cycle : build → package → sign → deploy → rollback → notify.

📦
PRODUIT LIÉ
Universal Installer V2.0
← Article précédent Article suivant →