Skip to content
FlightStack Docs
Sign in Start free

Pipeline Connections | FlightStack

Connections define the execution order between jobs in a pipeline. They determine which jobs run in sequence, in parallel, or wait for multiple dependencies.

A connection links a job’s output port to another job’s input port:

┌─────────────┐ ┌─────────────┐
│ Job A │●───────▶│ Job B │
└─────────────┘ └─────────────┘
output input

Job B will only start after Job A completes successfully.

Jobs run one after another:

┌───────┐ ┌───────┐ ┌───────┐
│ Test │────▶│ Build │────▶│Deploy │
└───────┘ └───────┘ └───────┘

Multiple jobs start from the same source:

┌───────────┐
┌───▶│ Build iOS │
│ └───────────┘
┌───────┐│
│ Test │├───▶┌───────────┐
└───────┘│ │Build Droid│
│ └───────────┘
│ ┌───────────┐
└───▶│ Build Web │
└───────────┘

All three builds start simultaneously after tests pass.

One job waits for multiple upstream jobs:

┌───────────┐
│ Build iOS │────┐
└───────────┘ │
┌───────────┐ ┌───────┐
│Build Droid│─▶│Notify │
└───────────┘ └───────┘
┌───────────┐ │
│ Build Web │────┘
└───────────┘

Notify only runs after all three builds complete.

Combine patterns for sophisticated pipelines:

┌───────────┐ ┌────────────┐
┌───▶│ Build iOS │────▶│ Deploy iOS │───┐
│ └───────────┘ └────────────┘ │
┌────┴───┐ ▼
│ Test │ ┌─────────┐
└────┬───┘ │ Notify │
│ ┌───────────┐ ┌────────────┐ ▲
└───▶│Build Droid│────▶│Deploy Droid│───┘
└───────────┘ └────────────┘
  1. Hover over a job’s right edge (output port)
  2. Click and drag toward another job
  3. Release on the target job’s left edge (input port)
  1. Click on the connection line
  2. Press Delete or Backspace

Or right-click the line and select “Remove”.

You cannot create loops:

❌ Invalid:
┌───────┐ ┌───────┐
│ Job A │────▶│ Job B │
└───────┘ └───────┘
▲ │
└────────────┘

Every pipeline needs at least one trigger connected to the first job(s):

┌──────────┐ ┌───────┐
│ Trigger │────▶│ Job │
└──────────┘ └───────┘

Jobs without incoming connections (except triggers) won’t execute:

┌──────────┐ ┌───────┐
│ Trigger │────▶│ Job A │ ← Runs
└──────────┘ └───────┘
┌───────┐
│ Job B │ ← Never runs (no connection)
└───────┘
  1. Pipeline triggered
  2. All jobs connected directly to trigger start
  3. As each job completes, downstream jobs check if all their dependencies are done
  4. If all dependencies succeeded, job starts
  5. If any dependency failed, downstream jobs are skipped

Each connection has an optional condition field. When set, the connection only “fires” if the expression evaluates truthy at runtime. This lets one job branch into different downstream paths based on its outputs or the run context.

The expression language is the same ${{ … }} interpolation used in variables and step outputs. Supported operators: ==, !=, <, <=, >, >=, &&, ||, !. Strings use single or double quotes.

${{ steps.<sourceJobId>.outputs.<name> == 'value' }}
${{ steps.test.outputs.failed == 0 && context.branch == 'main' }}
${{ steps.build.status == 'success' }}
${{ context.eventType == 'pullRequest' }}

Branch-conditional deploy:

ci-build ──┬── (condition: context.branch == 'main') ──▶ deploy-prod
└── (condition: context.branch != 'main') ──▶ deploy-staging

Skip notifications on success:

build ── (condition: steps.build.status != 'success') ──▶ notify-slack

Two-out-of-three fan-in:

A fan-in target with requires: any instead of the default all will start as soon as one upstream connection fires. Set this in the connection’s advanced options.

In the pipeline definition payload, each entry in connections accepts condition as a string. The visual editor shows a small diamond on the connection when a condition is set; clicking it opens the expression editor.

By default, if a job fails:

  • Downstream jobs are skipped (their incoming connections do not fire)
  • The pipeline run is marked as failed

Notification jobs can be configured to run on failure for alerts — wire them off your build jobs with condition: steps.build.status != 'success'.