makeplane / makeplane/plane

[bug]: feature-branch workflows publish to public Docker Hub, polluting release registries

Open
#9,054 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
59.6k
Forks
5.8k
Avg merge
1d 22h
Merged PRs (30d)
49

Description

Summary

makeplane/plane's build workflows publish Docker images to the public makeplane/* Docker Hub org for any workflow_dispatch invocation, regardless of which branch is selected. The branch name becomes the tag. As a result, makeplane/* (and the parallel makeplane/*-commercial repos, presumably built by a sibling private repo using the same shared action) accumulate hundreds of feature-branch, ephemeral, and label tags mixed in with semver releases.

This breaks automated dependency trackers (Renovate, Dependabot) for consumers of these images and leaks internal development state (branch names, fix descriptions, contributor shorthand) into a public registry.

Context

I hit this while setting up Renovate against a Kubernetes deployment of Plane Commercial Edition at my company, tracking the planeVersion Helm chart value automatically. Renovate proposed v2.5.3 → v2.11.1 as an "upgrade" — which led me down the rabbit hole of auditing the registry and figuring out why.

Evidence

Audited makeplane/backend-commercial on Docker Hub: 367 tags total.

Bucket Count Examples
Clean semver vX.Y.Z 65 v2.5.4, v2.5.3
CalVer vYY.MM.DD-N 2 v24.09.23-1, v24.09.22-1
*-phoenix-<sha> builds 44 v2.5.0-phoenix-0ab83bc
Branch names, labels, RCs, prerelease majors 256 buildcache, fixpnpmpathci, fix-pi-streaming, feat-auto-embedding-model-creation, v2.5.4-rc1, v3.0.0-guinness-4fb2ad3, stable, preview, chorereusedbconnections

The CE-side makeplane/* repos exhibit the same pattern — same workflows, same shared action.

Specific consumer impact:

  1. v2.11.1 (published 2025-10-17) version-sorts above v2.5.x but predates it in the real release timeline — and in fact was published ~7 weeks before v2.0.0 itself (2025-12-05). Renovate proposes v2.5.3 → v2.11.1 as an upgrade — actually a downgrade to a stale, out-of-band build.
  2. v24.09.23-1, v24.09.22-1 sort as major version 24, becoming the "newest" tag once v2.11.1 is excluded.
  3. v3.0.0-guinness-<sha> is a public v3.0.0 prerelease that would propose a phantom major upgrade if a tracker ever relaxed its prerelease filter.

Renovate workaround we landed on after several CI iterations:

"allowedVersions": "<v2.11.1 || >v2.11.1 <v24.0.0"

Root cause

Two workflows in this repo invoke the shared makeplane/actions/build-push@v1.4.0 composite action against arbitrary branches:

  • .github/workflows/build-branch.yml — auto-push is gated to preview / canary, but workflow_dispatch accepts any branch as input.
  • .github/workflows/feature-deployment.yml — explicitly designed to publish feature-branch previews, always via workflow_dispatch.

The shared action's tag-selection logic (in build-push/action.yml):

elif [ "${{ env.TARGET_BRANCH }}" == "master" ]; then
  TAG=${{ env.IMG_OWNER }}/${{ env.IMG_NAME }}:latest
  ...
else
  TAG=${{ env.IMG_OWNER }}/${{ env.IMG_NAME }}:${FLAT_BRANCH_VERSION}
  if [ "${{ env.PRIVATE_REGISTRY_PUSH }}" == "true" ]; then
    TAG=${TAG},${{ env.PRIVATE_REGISTRY_ADDR }}/...:${FLAT_BRANCH_VERSION}
  fi
fi

For any non-release, non-master invocation, the action pushes to public Docker Hub with the flattened branch name as the tag. The private-registry-push input adds a private target alongside the public push rather than replacing it — there is no way for a caller to publish privately only.

buildcache comes from the BuildKit cache-to: type=registry,ref=.../img:buildcache configuration pointing at the same public repo. stable, *-phoenix-<sha>, and v3.0.0-guinness-<sha> come from the release path with a permissive semver regex (^v[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9]+(-[a-zA-Z0-9]+)*)?$) that accepts arbitrary suffix chains.

Proposed fix

Two layers to consider, depending on where you'd prefer the gate:

At the caller (this repo):

  • Restrict feature-deployment.yml to push to registry.plane.tools only (or a separate makeplane/*-preview Docker Hub org), never the release repo.
  • Restrict build-branch.yml's workflow_dispatch mode to a ref allowlist (master, preview, canary, plus release tags).
  • Move BuildKit cache-to off the public release repo to a private cache target or GHA cache backend.

At the shared action (makeplane/actions):

  • Make public Docker Hub push opt-in rather than always-on. Add a public-registry-push boolean (parallel to private-registry-push), defaulting to false for non-release builds. This prevents the class of mistake for every consumer, including whichever private repo builds the *-commercial images.
  • Tighten the release-version regex to reject -<word>-<sha> style suffixes, or require an explicit prerelease flag and route them to a prerelease-namespaced tag.

The caller-side fix unblocks the immediate registry hygiene problem. The action-side fix is the systemic version. Both are worthwhile; the caller fix is the smaller patch.

Happy to open a PR if there's directional agreement on which approach you'd prefer.

Why this matters externally

For self-hosters tracking planeVersion automatically, every release the registry produces a new ambiguous tag that breaks the next upgrade proposal. The workaround range above is fragile — the next leaked v25.* or v3.0.1-foo tag will require another CI iteration and another Renovate config update. Cleaning this up at the source benefits every consumer of the public images.

Beyond the tooling impact, it also just looks messy. A public registry surfacing tags like fixpnpmpathci, chorereusedbconnections, and feat-auto-embedding-model-creation alongside semver releases reads as either unmaintained or careless to anyone browsing the tag list. Branch-name internal state (in-flight feature names, fix descriptions, contributor shorthand) is visible to anyone with a Docker Hub account. For the self-hosters and integrators who do look — anyone wiring up automation, debugging an image pull, or evaluating the project's release discipline — the registry reads as part of the public surface. Worth treating it as one.

Immediate ask

Independent of any workflow changes, it would be great to get the three tags that actively break version-aware trackers retagged or removed from makeplane/*-commercial (and makeplane/* if present there too):

  • v2.11.1
  • v24.09.23-1
  • v24.09.22-1

These are the ones that cause incorrect upgrade proposals today. Removing them lets consumers drop the allowedVersions workaround and unblocks normal version tracking while the longer-term fix is being scoped.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with .github/workflows/build-branch.yml and feature-deployment.yml, then inspect the referenced makeplane/actions/build-push@v1.4.0 action and its build-push/action.yml. Compare workflow_dispatch ref handling, registry targets, and cache-to behavior; done means feature builds no longer pollute public release repositories while intended release publishing still works.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, github-actions
Domain
ci-cd, devops, release
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.