Actions reference

Actions add menu items that appear on the detail-view kebab and (optionally) the list-view bulk-actions dropdown. Register one with buoy.addAction({...}):

buoy.addAction({
  match: { group: "argoproj.io", kind: "Rollout" },
  id: "abort",
  label: "Abort",
  danger: true,
  when: (obj) => obj.status?.phase === "Progressing",
  confirm: {
    phrase: (obj) => obj.metadata.name,
    title: (obj) => `Abort rollout ${obj.metadata.name}?`,
  },
  run: async (ctx) => {
    await ctx.statusPatch({ status: { abort: true } });
  },
});

Required fields

fieldtypenotes
match{ group, kind }Exact match. group: "" for core kinds.
idstringUnique within this plugin.
labelstringMenu item text.
run(ctx) => PromiseThe body. See Run callback.

Optional fields

fieldtypenotes
dangerbooleanRed styling + the standard danger ConfirmModal look.
bulkbooleanAlso show in ListView’s bulk-actions menu.
alsoSingleboolean (default true)When bulk: true, controls whether the item also shows for single objects.
iconstringOptional lucide icon name (matches built-in icon catalog).
when(obj) => booleanHide the action when this returns false.
confirmActionConfirmSpecSee Confirm gating.

Run callback

run(ctx) receives a pre-bound context. The patch helpers wrap Buoy’s plugin_patch Tauri command so you only supply the JSON body.

run: async (ctx) => {
  // ctx.obj — the live object
  // ctx.resource — resource string (e.g. "rollouts")
  // ctx.context  — kube context name (or null)
  // ctx.namespace — object namespace (or null for cluster-scoped)
  // ctx.name      — object name

  await ctx.mergePatch({ spec: { replicas: 3 } });
  // or:
  await ctx.strategicPatch({ spec: { template: { metadata: { labels: { x: "y" } } } } });
  await ctx.jsonPatch([{ op: "add", path: "/metadata/labels/x", value: "y" }]);
  await ctx.statusPatch({ status: { abort: true } });
  await ctx.delete();
}

Throwing from run aborts the action and surfaces the error inside the ConfirmModal — no need to wrap in try/catch unless you want to translate the message.

For bulk actions, run is called once per selected row with the appropriate ctx.

Confirm gating

Every action goes through ConfirmModal — the same red typing-required dialog the built-in Delete uses. Configure it via confirm::

confirm: {
  phrase: (obj) => obj.metadata.name,                       // user types this to enable Confirm
  title:  (obj) => `Delete ${obj.metadata.name}?`,          // dialog title
  body:   "This will tear down the workload immediately.",  // optional explainer
}

Each field accepts either a plain string or a (obj) => string callback. Use the callback when the confirm needs object data.

For bulk actions, the confirm fields receive the first selected object, while the typed phrase becomes the verb summary (e.g. DELETE 3 pods).

Tips

  • Don’t reach for actions for everything. If the underlying operation is just a relabel, the built-in Edit Labels modal is usually faster than a plugin action.
  • Use when to keep menus tidy. Hide actions that don’t apply to the current object state. E.g. a “Pause Rollout” action’s when: (obj) => !obj.spec?.paused keeps it from showing up next to “Resume”.
  • Prefer statusPatch for /status subresources. Many CRDs reject writes to status through the main resource; the helper hits the right endpoint.
  • Patches are sent as the active impersonation. If /as <user> is on, the action runs as that user; RBAC denials surface in the modal.

Edit this page on GitLab