Skip to content

[Feature] Per-service tag filter for triggerType: tag (monorepo / release-please) #4995

Description

@elisiumm

Summary

When triggerType: tag is used, a single pushed tag triggers every application/compose in the repo that is configured to deploy on tag — there is no way to scope which service a given tag should deploy. For a monorepo where each service has its own tag prefix (very common with release-please + node-workspace, which emits per-package tags like web-v0.7.1, api-v0.5.1, shared-v0.5.1), this means a web-* release needlessly rebuilds and redeploys the API, and vice versa.

Feature request

Add an optional tag filter (glob/pattern) per application (and compose), analogous to the existing Watch Paths feature for branch pushes. When set, the service deploys on a tag only if the tag name matches the pattern; when empty, behavior is unchanged (any tag deploys — fully backward compatible).

Example config for a release-please monorepo:

Service Tag filter
front web-v*
api api-v*
both (shared contract) additionally match shared-v*

Why the current mechanisms don't cover this

  • Watch Paths (watchPaths + shouldDeploy with micromatch) already solves the equivalent problem for branch pushes — but it is only evaluated on the push-to-branch path of the webhook, not on the tag path.
  • On the tag path, apps/dokploy/pages/api/deploy/github.ts finds all apps with triggerType = "tag" for the repo and enqueues a deployment for each, in a for (const app of apps) loop, without ever comparing against tagName (the tag name is only used for the deployment title). So there is no hook where a per-service tag pattern could take effect today.

Suggested implementation (small, mirrors Watch Paths)

  1. Schema: add an optional tagFilter: string | null (or tagFilters: string[]) column on application and compose (packages/server/src/db/schema/), plus a Drizzle migration.
  2. Filter helper: reuse micromatch (already a dependency, used by watch-paths/should-deploy.ts). Something like:
    export const matchesTag = (tagFilter: string | null | undefined, tagName: string): boolean => {
      if (!tagFilter) return true; // empty = deploy on any tag (backward compatible)
      return micromatch.isMatch(tagName, tagFilter);
    };
  3. Webhook: in the tag branch of github.ts, skip apps whose tagFilter doesn't match tagName before enqueuing — for both the applications and compose loops.
  4. UI: expose a "Tag Filter" input next to the existing "Watch Paths" field in the Git provider settings (save-git-provider.tsx / save-git-provider-compose.tsx), shown when triggerType === "tag".

This keeps the tag path symmetric with the branch path (Watch Paths), is opt-in, and is fully backward compatible (empty filter = today's behavior).

Use case / impact

Monorepo with release-please (node-workspace plugin) emitting per-component tags. Today a single release that only touched the frontend still rebuilds the backend (a heavier build), doubling deploy time and resource use on the build node for no reason. A per-service tag filter lets each service deploy only on its own tag prefix, with shared-* fanning out to both when the shared contract changes.

Environment

  • Dokploy v0.29.13.
  • triggerType: tag, GitHub source, monorepo (pnpm workspace) with release-please per-package tags.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions