Skip to content

Pipeline stage added without source hides the pipeline's existing stages #8582

Closed

Description

@cstns

Adding a pipeline stage without source to a pipeline that already has stages doesn't append it. It becomes a second unlinked head, and the pipeline listing then shows only the new stage while the existing ones disappear from it.

Reproduced locally:

before: GET /api/v1/applications/:id/pipelines -> stages: ['GitStage']
POST /api/v1/pipelines/:id/stages  {"name":"NoSource","instanceId":"..."}   (no source)
after:  GET /api/v1/applications/:id/pipelines -> stages: ['NoSource']

GitStage is still there. Fetching it directly at /api/v1/pipelines/:id/stages/VvrL7OLazm returns 200 with its data intact. Both stages have NextStageId: null, so the listing presumably walks from one head and picks the newer one.

The effect is that a single call with a missing source looks like it wiped the pipeline, and the older stages can't be reached through the listing afterwards even though nothing was deleted.

Might be worth either rejecting a source-less stage when the pipeline already has stages, or appending it to the end automatically, or at least having the listing return every stage rather than only the ones reachable from one head.

Activity

  1. andypalmi commented on Sep 22, 2026

    @andypalmi
    Contributor

    Adding a stage without source to a pipeline that already has stages doesn't attach it to the chain. It becomes a second, disconnected stage, and the pipeline listing then shows only that new stage, hiding the existing ones. Nothing is actually deleted, but it looks like the pipeline was wiped.

    Three ways we could fix this:

    1. Reject it: return a 400 if a stage is added without source when the pipeline already has stages. Adding the very first stage still works. Downside: this rejects requests that succeed today.
    2. Auto-append it: automatically link the new stage to the end of the chain. Most forgiving, but the API decides the position for the caller.
    3. Fix only the listing: leave the write behaviour as-is, but make the listing return all stages so nothing disappears. Downside: the disconnected stage still exists in the data.

    I lean towards option 1, since the point of source is to say where the stage goes, and dropping it should be treated as a mistake rather than silently guessed. Happy to go with 2 if we'd rather be forgiving. Any preference before I pick one up?

  2. added this to the 3.2 milestone on Oct 12, 2026
  3. self-assigned this
    on Oct 12, 2026
  4. moved this to In Progress in 🛠 Developmenton Oct 14, 2026
  5. moved this from In Progress to Review in 🛠 Developmenton Oct 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:apiWork on the platform APItype:bugSomething isn't working

Type

No type

Projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions