Vous avez déployé un hotfix vendredi. Le lundi, le support reçoit encore des messages d'utilisateurs qui ne l'ont jamais reçu, les bêta-testeurs sont bloqués sur un bundle obsolète, et un client entreprise veut savoir exactement quelle version utilise son équipe terrain. C'est à ce moment qu'il devient évident qu'une notification de mise à jour d'app n'est pas une modale. C'est un système d'exploitation pour le contrôle des releases.
Dans les projets Capacitor et Electron, la difficulté n’est généralement pas de détecter qu’une mise à jour existe. Le plus dur, c’est tout ce qui l’entoure : décider qui doit la voir et quand, ce qui doit se passer s’ils l’ignorent, comment la mise à jour circule dans le CI/CD, et ce que la télémétrie vous indique après le déploiement. Si vous traitez les prompts de mise à jour comme de simples éléments de décoration UI, vous obtenez des relances bruyantes, une logique de release fragile et des utilisateurs confus. Si vous les traitez comme une partie intégrante du cycle de vie du produit, vous obtenez des déploiements plus sûrs et une file de support bien plus calme.
Table des matières
- Pourquoi votre stratégie de mise à jour compte
- Implémenter la détection de mise à jour avec Capgo
- Concevoir des patterns de notification efficaces
- Automatiser les mises à jour et le choix utilisateur
- Déploiements progressifs avancés avec canaux et télémétrie
- Dépanner les problèmes de notification courants
Pourquoi votre stratégie de mise à jour compte
Mises à jour : la rétention, pas seulement la maintenance
Les équipes présentent souvent les mises à jour comme une corvée de maintenance. Corriger le bug, afficher un prompt, passer à autre chose. Cette approche ignore l’impact produit.
Les notifications push sont l’un des rares canaux du cycle de vie capables de ramener les utilisateurs dans l’application après l’installation. Données résumées par la recherche d’Invesp sur les notifications push mobiles says push notifications can boost app engagement by jusqu'à 88 %, et les utilisateurs qui acceptent sont conservés à près de 2 fois le taux de ceux qui ne le font pas. Pour la stratégie de mise à jour, c'est crucial : chaque client obsolète est un utilisateur qui ne verra peut-être jamais la fonctionnalité, le correctif ou le changement de conformité que vous venez de déployer.
Un flux de mise à jour faible crée généralement trois problèmes à la fois :
- Retard produit means new features launch unevenly, so PMs read mixed signals from analytics.
- Charge support les agents doivent demander des captures d'écran, des versions et des détails d'appareil avant même de pouvoir reproduire un problème.
- Exposition sécurité les anciens clients continuent d'interagir avec des API qui ont déjà évolué.
Règle pratique : considérez la livraison des mises à jour comme une partie de la gestion des releases, et non comme un simple message de courtoisie en fin de sprint.
Mises à jour store et live updates : des problèmes différents
Les mises à jour sur l’App Store et le Play Store restent essentielles. Les modifications de dépendances natives, les releases imposées par les politiques, les changements de permissions et les correctifs au niveau binaire y appartiennent. Mais les mises à jour pilotées par les stores ne sont qu’une couche du système, et elles sont lentes par conception, car la revue et l’adoption par les utilisateurs échappent à votre contrôle direct.
Pour les applications Capacitor et Electron, les live updates couvrent une autre catégorie de travail. Elles conviennent aux modifications du bundle web, comme le JavaScript, le CSS, les textes, les assets et les feature flags qui ne nécessitent pas un nouveau binaire. En pratique, cela signifie que vous pouvez séparer deux questions de release :
| Question de release | Le plus adapté |
|---|---|
| Cette modification nécessite-t-elle un nouveau binaire natif ? | Release sur les stores |
| Ce changement peut-il être livré en bundle web en toute sécurité ? | Live update |
| Do users need to know before continuing? | Décision de notification in-app |
| Seuls certains utilisateurs en ont-ils besoin maintenant ? | Déploiement par canal |
That split is why agencies building client apps should stop designing around a single “update available” pop-up. Professional teams need soft prompts, silent apply paths, rollback rules, channel targeting, and logs that support can inspect later.
La question de la confiance compte aussi. Les utilisateurs ne craignent pas tant les mises à jour que les interruptions imprévisibles. Si l'app se met à jour de façon fluide, explique clairement les changements majeurs et ne bloque l'usage qu'en cas de dysfonctionnement réel ou de risque de sécurité, c'est perçu comme une preuve de compétence.
Implémenter la détection de mise à jour avec Capgo
La première étape est simple : savoir quelle version l'utilisateur utilise, à quel canal il appartient, et décider s'il y a quelque chose à récupérer. La plupart des systèmes de mise à jour faits maison deviennent ingérables parce qu'ils mélangent ces décisions. Gardez-les séparées.

Commencez par identifier la version
Un updater fiable nécessite trois valeurs disponibles à l’exécution :
- Version de l’app installée
- Canal de release assigné
- État actuel de la mise à jour, comme idle, checking, available, downloading, ready, failed
Si vous omettez ce modèle d’état, les bugs de notification apparaissent vite. L’app vérifie trop souvent. Le même prompt s’affiche à chaque lancement. Un téléchargement en arrière-plan se termine, mais l’UI indique toujours « checking ».
Un service managé est généralement le bon choix ici, pour une raison : le travail opérationnel est plus lourd que ne le suggère le snippet code. Il vous faut des bundles signés, des règles de canal, la prise en charge du rollback, un historique des versions, des logs au niveau de l’appareil et une infrastructure de livraison. Capgo fournit cette fonctionnalité pour Capacitor et les applications Electron via un plugin de mise à jour et un workflow de livraison hébergé, ce qui explique pourquoi la plupart des équipes clientes ont tout intérêt à l’utiliser plutôt que de reconstruire la stack en interne.
Intégrez l'updater au démarrage de l'app
Au lancement de l’app, effectuez une vérification légère une fois votre shell prêt. N’empêchez pas le premier rendu, sauf si l’app ne peut pas continuer sans la mise à jour.
Un schéma typique dans une application Capacitor ressemble à ceci :
import { App } from '@capacitor/app'
// import your updater SDK here
type UpdateDecision =
| { kind: 'none' }
| { kind: 'soft'; version: string }
| { kind: 'hard'; version: string }
| { kind: 'silent'; version: string }
async function checkForUpdate(): Promise<UpdateDecision> {
try {
// Replace with your updater SDK call
const result = await updater.check()
if (!result || !result.available) {
return { kind: 'none' }
}
if (result.metadata?.mandatory === true) {
return { kind: 'hard', version: result.version }
}
if (result.metadata?.silent === true) {
return { kind: 'silent', version: result.version }
}
return { kind: 'soft', version: result.version }
} catch {
return { kind: 'none' }
}
}
App.addListener('appStateChange', async ({ isActive }) => {
if (!isActive) return
const decision = await checkForUpdate()
handleUpdateDecision(decision)
})
L’objectif de check() isn’t just “is there a newer thing”. It’s “is there a newer thing for cet utilisateur sur cet canal, et comment l’app doit réagir ».
Une implémentation saine enregistre aussi l’heure de la dernière vérification réussie et la dernière version proposée. Cela permet de garder votre logique de notification de mise à jour idempotente plutôt qu’insistante.
Lisez le résultat et branchez tôt
Le branchement doit se faire au plus près du résultat du check. Ne dispersez pas les règles de mise à jour entre les écrans.
Voici la répartition pratique que j'utilise :
- No update means do nothing and log a normal check result.
- Mise à jour douce means queue a banner, settings badge, or lightweight in-app prompt.
- Mise à jour silencieuse signifie télécharger en arrière-plan et activer au prochain lancement.
- Mise à jour forcée signifie basculer l'app vers un flux de blocage contrôlé.
Plus tard dans l'implémentation, j'aime exposer cette décision via un store central, pour que les UI React, Vue ou Ionic puissent la consommer de façon cohérente.
Ce guide est utile si vous voulez voir la configuration globale autour d'une app Capacitor :
Gardez la couche de détection simple. L’ingéniosité doit être dans la politique de déploiement, pas dans le démarrage code.
Concevoir des patterns de notification efficaces
La plupart des prompts de mise à jour échouent parce que l’équipe a choisi un seul modèl’et l’a utilisé partout. C’est comme ça qu’on finit par afficher une modale bloquante pour une simple retouche de texte, ou par cacher une migration critique derrière un toast que personne ne remarque.
L'environnement est déjà saturé. Résumé du benchmark Airship de Business of Apps indique que l'utilisateur moyen de smartphone aux États-Unis reçoit 46 notifications push par jour, alors que les taux moyens de réaction et de clic restent modestes à 3,4 % sur iOS et 4,6 % sur Android. Une notification de mise à jour d'app doit capter l'attention sans épuiser l'utilisateur.

Utilisez le modèle le moins intrusif qui soit efficace
Une bonne interface de mise à jour respecte le coût de l'interruption. Si l'utilisateur saisit des coordonnées bancaires, note un dossier patient ou scanne un inventaire, une modale peut être pire que le bug que vous tentez de corriger.
Je cartographie généralement ce type de schéma :
- Bandeau en haut ou en bas for minor fixes, low urgency improvements, and silent-update confirmation.
- Toast pour le statut en arrière-plan, comme « Mise à jour prête au prochain lancement », mais pas pour les décisions importantes.
- Point d’entrée des paramètres ou du profil pour les utilisateurs qui veulent du contrôl’et la visibilité des changelogs.
- Modale bloquante uniquement lorsque l’app ne peut pas continuer en toute sécurité sur l’ancienne version.
Une bannière discrète fait souvent plus de travail qu’une modale dramatique, car elle n’oblige pas l’utilisateur à lutter contre l’interface.
Comparaison rapide des principaux patterns
| Modèle | Idéal pour | Principal risque | Note d’implémentation |
|---|---|---|---|
| Bannière | Mises à jour optionnelles, relances à faible urgence | Facile à ignorer | Mémoriser l’ignorance par version |
| Toast | Changements d’état en arrière-plan | Disparaît trop vite | Associer à une entrée de paramètres durable |
| Message in-app | Déploiements progressifs contextuels | Peut ne pas être vu rapidement | Lier à un écran pertinent |
| Modale | Action obligatoire | Frustration de l’utilisateur | Réservé aux blocages critiques uniquement |
Le détail d’implémentation le plus important est Persistance d'état. Si l’utilisateur clique sur « Plus tard », associez ce choix à la version proposée. S’il ferme une bannière, ne la réaffichez pas à chaque changement de route. Si vous oubliez cela, les utilisateurs considéreront l’application comme cassée, même si le mécanisme de mise à jour fonctionne.
Pour les équipes qui utilisent déjà les notifications push dans leur stack, il est utile de comparer l’UX des mises à jour d’app à votre configuration de messagerie globale. Le guide de Capgo Ionic et les notifications push Capacitor avec Firebase est utile ici, car il aide à séparer les préoccupations de transport des surfaces in-app qui demandent à l’utilisateur d’agir.
Le push ne fait pas tout
Une erreur courante consiste à supposer que les badges de mise à jour au niveau du système d’exploitation et les notifications du store suffisent. En réalité, les utilisateurs manquent souvent ces alertes à cause des paramètres de l’appareil, des autorisations de badge, du comportement de mise à jour automatique ou des modes d’économie d’énergie. C’est pourquoi la messagerie in-app reste essentielle, même lorsque l’écosystème du store fonctionne correctement.
Pour Electron, c’est encore plus évident. Les utilisateurs de bureau s’attendent souvent à des indicateurs de statut discrets, et non à des interruptions modales. Un petit chip « Mise à jour prête » dans la coquille peut être plus professionnel qu’une boîte de dialogue système qui vole le focus en plein milieu d’un flux de travail.
Le meilleur pattern est celui qui correspond au risque de la mise à jour et à la tâche en cours de l’utilisateur. Le reste est du théâtre.
Automatiser les mises à jour et le choix utilisateur
Une fois la détection et les patterns UX en place, le cœur du système est le workflow. À l’intérieur, les équipes finissent souvent par sur-automatiser et perdre le contrôle, ou sous-automatiser et créer une dette de support.

Les recommandations de maintenance d’app de Coderio préconisent un rythme de release pratique de mises à jour mineures toutes les 2 à 4 semaines et releases majeures tous les 3 à 6 mois, en réservant les mises à jour forcées aux problèmes critiques de sécurité ou de stabilité. C’est le bon modèle mental. La décision doit découler du type de release, pas de l’anxiété du développeur.
Silent updates for low-risk changes
Les mises à jour silencieuses sont la voie la moins exploitée dans les apps Capacitor. Si vous avez corrigé le style, le copy, le câblage d’un feature flag ou un bug JavaScript non bloquant, il n’y a généralement aucune raison d’interrompre l’utilisateur.
Le flux est simple :
- L’app vérifie la présence d’un nouveau bundle.
- Si la mise à jour est marquée comme sûre à appliquer en arrière-plan, elle se télécharge en arrière-plan.
- L’app active le nouveau bundle au prochain lancement.
- L’utilisateur peut voir une brève note « Mise à jour réussie » après le redémarrage, ou rien du tout.
Ce dernier choix dépend de la nature du changement. Si la mise à jour a modifié un flux de travail visible, une petite carte « Nouveautés » au prochain lancement aide à s’y retrouver. Sinon, le silence est de mise.
Un gestionnaire d’état simple peut ressembler à ceci :
async function handleUpdateDecision(decision: UpdateDecision) {
if (decision.kind === 'silent') {
await updater.download()
await updater.setNextBundle()
localStorage.setItem('pendingUpdateVersion', decision.version)
return
}
if (decision.kind === 'soft') {
showBanner(decision.version)
return
}
if (decision.kind === 'hard') {
showForcedUpdateScreen(decision.version)
}
}
Flux de choix utilisateur pour les changements produit visibles
Un flux de choix utilisateur est adapté lorsque la mise à jour modifie suffisamment le comportement pour que les utilisateurs doivent accepter l’interruption. Une nouvelle navigation, un onboarding révisé, un flux d’approbation modifié ou une refonte importante du dashboard relèvent tous de cette catégorie.
Le prompt doit rester ciblé :
- Ce qui a changé
- Pourquoi c'est important
- Ce qui se passe s’ils mettent à jour maintenant
- Que se passe-t-il s’ils attendent
Évitez les poèmes de release notes dans la boîte de dialogue. Une phrase claire et deux boutons surpassent généralement un pavé de texte.
J’aime ce modèle :
Nouvelle version disponible. Elle inclut le workflow de reporting mis à jour et corrige un problème d’export. Mettre à jour maintenant ou continuer et installer plus tard.
Utilisez « Plus tard » avec discernement. Si l’ancien client reste valide, laissez l’utilisateur continuer. Si l’ancien client va casser à cause d’une migration API, ne faites pas semblant que c’est optionnel.
Pour les équipes qui envisagent la gouvernance au-delà de la livraison d’applications, la même logique apparaît dans les opérations de sécurité. Une bonne automatisation gère silencieusement les changements de routine et n’escalade que lorsque le risque le justifie. C’est l’une des raisons pour lesquelles ce résumé de security automation for SOC teams est utile. Il montre le principe de conception plus large : classifier les événements, automatiser les chemins sûrs et rendre l’interruption humaine intentionnelle.
Vous pouvez également resserrer cela avec une logique d’audience. L’article de Capgo sur usage frequency segmentation for app updates est une référence pratique, car les utilisateurs fréquents et occasionnels ne devraient pas toujours recevoir le même timing ou le même style de prompt.
Mises à jour forcées pour les cas critiques ciblés
Les mises à jour forcées sont légitimes. Elles sont aussi faciles à abuser.
Utilisez une porte dure si l’une de ces conditions est vraie :
| Condition | Mise à jour forcée |
|---|---|
| Correctif de sécurité avec exposition connue | Oui |
| Problème de stabilité provoquant une rupture sévère | Oui |
| Contrat backend cassant | Oui |
| Petites retouches d’interface | Non |
| Déploiement progressif d’une fonctionnalité optionnelle | Non |
L’implémentation doit être explicite. Vérifiez la version installée au lancement, comparez-l’à votre version minimale prise en charge et placez l’utilisateur dans un état bloqué uniquement s’il est en dessous de ce seuil. Ne déduisez pas « obligatoire » du simple fait qu’une version plus récente existe.
Un écran de mise à jour forcée nécessite trois propriétés :
- Pas d’impasse. Give the user a clear retry path.
- Explication claire. Expliquez-lui pourquoi la mise à jour est requise.
- Gestion du mode hors ligne. Si le réseau est indisponible, expliquez-l’aussi.
Ce qui ne fonctionne pas, c’est une modale avec un seul bouton « Mise à jour » qui échoue sans indication sur une connexion mobile instable. Si l’app est bloquée, le chemin de récupération doit être plus soigné que le chemin normal.
Déploiements progressifs avancés avec canaux et télémétrie
La plupart des incidents de mise à jour ne surviennent pas parce que la détection a échoué. Ils surviennent parce que l’équipe a déployé largement avant d’avoir compris ce que la mise à jour faisait en conditions réelles.
Les canaux réduisent le rayon d'impact
Le déploiement progressif par canaux est la façon la plus sûre de livrer des live updates dans les apps clients. Au lieu de publier un seul bundle pour tout le monde, publiez vers des audiences telles que interne, QA, bêta, staging, production, ou même des flux spécifiques à certains clients.
Cela vous donne une forme de release qui ressemble davantage à un contrôl’opérationnel qu’à un lancement binaire. Un seul build peut traverser une séquence d’audiences, chaque audience vous donnant confiance avant que le groupe suivant ne le voie.
Voici un aperçu utile du volet commercial de ce modèle de déploiement, notamment la structure des plans autour des workflows de mise à jour.

Cela compte aussi pour la stratégie de notifications. Les bonnes pratiques de notifications push d'Adapty indiquent que l'optimisation des heures d'envoi peut augmenter les taux de réaction de 40 % et un ciblage avancé peut tripler les taux de réaction. In update systems, that translates into channel-aware rollout and version-specific messaging, not blanket prompts to the whole install base.
La télémétrie vous indique si les utilisateurs ont réellement migré
Un système de mise à jour professionnel doit répondre à ces questions sans que l'ingénierie ait à fouiller dans des logs ad hoc :
- Sur quelle version de bundle se trouve chaque appareil ?
- La mise à jour a-t-elle été téléchargée ?
- S’est-elle appliquée avec succès au lancement suivant ?
- Les échecs de démarrage ont-ils augmenté après le déploiement ?
- Quels utilisateurs sont bloqués sur une version obsolète ?
C’est là que la télémétrie transforme les mises à jour d’un acte de release ponctuel en un processus opérationnel. Sans elle, vous ne savez que ce que vous avez déployé. Avec elle, vous savez ce que les utilisateurs ont adopté.
Si le support ne peut pas voir l’état de la mise à jour, il escaladera un problème produit qui est en réalité un problème de déploiement.
Je préfère nettement les chronologies par appareil aux dashboards purement agrégés. Les courbes d’adoption agrégées sont utiles, mais elles n’expliqueront pas pourquoi un client entreprise ouvre encore l’application sur un ancien bundle après une semaine. Les logs au niveau de l’appareil, eux, le feront.
La publication ciblée par version devient aussi plus pratique lorsque vous pouvez isoler des cohortes spécifiques. Ce guide sur envoyer une version spécifique aux utilisateurs est un bon exemple du type de contrôle dont les équipes d’entreprise finissent généralement par avoir besoin lorsqu’elles gèrent plusieurs environnements clients.
Le CI/CD doit publier et observer, pas seulement compiler
Un pipeline moderne ne doit pas s’arrêter à « build réussi ». Il doit :
- Compiler le bundle
- Signez et publiez sur le bon canal
- Ajoutez les métadonnées de la release
- Surveillez l'adoption et les échecs
- Effectuez un rollback si l'état de santé se dégrade
Le rollback, c'est ce qui distingue un outil de mise à jour de démo d'un outil de production. Si un bundle provoque des plantages au lancement ou des blocages au démarrage, les équipes doivent pouvoir contenir l'impact rapidement. C'est l'une des raisons majeures pour lesquelles une solution managée surpasse le DIY pour la plupart des agences. La livraison, les garde-fous, l'observabilité et le rollback ne sont pas des fonctionnalités secondaires. Ils constituent le système.
L'intégration CI/CD en elle-même n'a pas besoin d'être complexe. Ce qui compte, c'est que la publication soit déterministe et traçable. Une release doit pouvoir être attribuée à un commit, un environnement, un acteur et un canal. Si vous ne pouvez pas répondre rapidement à ces quatre points, la gestion des incidents devient vite pénible.
Dépanner les problèmes de notification courants
Les problèmes ci-dessous apparaissent régulièrement dans Capacitor et les mises à jour Electron. La plupart viennent d'une dérive d'état, et non du réseau.
Le prompt s'affiche à chaque lancement
Symptôme : les utilisateurs ferment la notification de mise à jour de l'app, mais elle réapparaît à chaque ouverture.
Cause probable : vous vérifiez correctement, mais vous ne conservez pas l'état du prompt par version proposée.
Solution : stockez la version que l'utilisateur a ignorée ou reportée, et comparez-l’avant d'afficher à nouveau l'UI.
function shouldPrompt(version: string): boolean {
const dismissed = localStorage.getItem('dismissedUpdateVersion')
return dismissed !== version
}
function dismissPrompt(version: string) {
localStorage.setItem('dismissedUpdateVersion', version)
}
C'est aussi là que les équipes confondent « disponible » et « doit interrompre ». Ce sont deux décisions différentes.
Mises à jour silencieuses : téléchargées mais jamais activées
Symptôme : les logs montrent qu'un bundle a été récupéré, mais l'ancienne UI continue de se charger.
Cause probable : l'app a téléchargé la mise à jour mais ne l'a jamais marquée pour le prochain lancement, ou votre chemin de démarrage pointe toujours vers le dernier bundle actif.
Solution : rendez l'activation explicite et vérifiez-l’au démarrage. Traitez « téléchargé » et « actif » comme des états distincts dans code et vos analytics.
De nombreux bugs disparaissent lorsque vous modélisez le cycle de vie comme available -> downloading -> ready -> active plutôt qu'un seul booléen.
Les vérifications se comportent différemment en dev et en production
Symptôme : la détection de mise à jour fonctionne sur un build de release mais pas en développement local, ou inversement.
Cause probable : configuration spécifique à l'environnement. Des noms de canaux différents, des plugins désactivés en debug, ou un code au démarrage enveloppé dans le mauvais guard.
Solution : rendez le comportement de l'environnement visible. Loggez le canal, la version de l'app et le mode de build au démarrage. Ne vous fiez pas à votre mémoire.
- Les builds de développement devraient généralement contourner les vérifications live update ou pointer vers un canal de test dédié.
- Les builds de staging doit se comporter comme la production, mais sur des flux de déploiement progressif isolés.
- Les builds de production ne doivent jamais partager de canaux avec le trafic QA interne.
Users are offline during the check
Symptôme : l'application affiche un état de mise à jour corrompu lorsque l'utilisateur l'ouvre sans connectivité.
Cause probable : le chemin de vérification suppose un succès réseau et mappe l'échec vers une interface d'erreur au lieu d'un état neutre.
Solution : dégrader proprement. Gardez la version actuelle active, enregistrez l'échec de la vérification et réessayez plus tard quand l'application redeviendra active.
Le mode hors ligne est une condition d'exécution normale, pas une exception.
Pour les mises à jour forcées, le mode hors ligne nécessite une attention particulière. Si la version minimale supportée est déjà invalide, l'application peut devoir rester bloquée. Dans ce cas, expliquez clairement la raison et proposez une action de réessai dès que la connectivité revient. Si la mise à jour est optionnelle, ne pénalisez jamais l'utilisateur pour une perte de réseau temporaire.
Le principe récurrent dans tous ces cas est simple : séparer détection, politique, UI, et activation. Lorsque ces préoccupations se concentrent dans un seul hook ou un seul composant d'écran, le débogage devient un jeu de devinettes.
Si votre équipe déploie des applications Capacitor ou Electron et a besoin d'un système de mise à jour contrôlé avec canaux, livraison de bundles signés, protection contre le rollback et observabilité au niveau de l'appareil, Capgo mérite d’être évalué. Il convient aux équipes qui veulent que les live updates se comportent comme une infrastructure de release, plutôt que comme un projet annexe bricolé.
Continuer depuis Stratégies efficaces de notification de mise à jour d’app
Si vous utilisez Stratégies efficaces de notification de mise à jour pour planifier l'automatisation CI/CD, et le connecter avec CI/CD Capgo pour le workflow produit dans le CI/CD de Capgo, Capgo Native Build pour le workflow produit dans les Native Builds de Capgo, Intégrations Capgo pour le workflow produit dans les intégrations de Capgo, Intégration CI/CD pour le détail d'implémentation dans l'intégration CI/CD, et Intégration GitHub Actions pour les détails d'implémentation de l'intégration GitHub Actions.