Pass artifacts as inputs and outputs across pipelines

Child pipeline steps support artifacts: input: and artifacts: output: to pass files across the parent/child boundary. Combined with variable passing, this gives child pipelines a complete function-call interface:

Mechanism

Pipeline key

Analogy

Scalar arguments

input-variables

String/number parameters

File inputs

artifacts: input:

File/blob arguments

Return values

artifacts: output:

Return files

This makes it possible to build child pipelines that behave like fully parameterised, self-contained operations — they receive everything they need, do their work, and return their outputs.


Syntax

Add artifacts: input: and/or artifacts: output: to any step of type: pipeline:

- step: name: Run Security Scan type: pipeline custom: security-scan input-variables: SCAN_LEVEL: strict artifacts: input: - app.tar.gz # path-based reference - production-build # named artifact reference output: - reports/security.json # path-based reference - security-report # named artifact reference

Step Properties

Property

Required

Description

type

Must be pipeline to use artifact I/O

custom

Name of the custom pipeline to run in the child

input-variables

Map of key/value pairs passed to the child (see Variable Sharing)

artifacts: input:

Artifacts from the parent to push into the child before it runs

artifacts: output:

Artifacts from the child to pull back into the parent after it completes


How It Works

Parent Pipeline ├── Step: Build ← produces app.tar.gz │ artifacts: [app.tar.gz] ├── Step: Security Scan ← type: pipeline │ artifacts: │ input: ← app.tar.gz pushed INTO child │ - app.tar.gz │ output: ← security-report.json pulled OUT of child │ - security-report.json │ │ │ └── Child: security-scan │ ├── Step: Scan dependencies │ └── Step: Generate report │ artifacts: [security-report.json] └── Step: Notify ← security-report.json available here script: - cat security-report.json
  1. Before the child runs — the parent collects each item listed in artifacts: input: from its own artifact context and makes them available inside the child pipeline.

  2. Child executes — the child runs normally. Input artifacts are available as regular files at their declared paths. The child doesn't need to declare anything special.

  3. After the child completes — the parent collects each item listed in artifacts: output: from the child's artifact context and adds them to its own context, making them available to all subsequent parent steps.

The contract is entirely defined on the parent side. The child pipeline needs no special declarations — it reads input files at the expected paths and produces output files at the expected paths using standard artifacts: blocks.


Referencing Artifacts

Each entry in artifacts: input: and artifacts: output: is a list item that can be either:

By File Path

Reference a specific file or glob path:

artifacts: input: - dist/app.tar.gz - config/runtime-settings.json output: - reports/scan-results.json - coverage/lcov.info

By Named Artifact

Reference an artifact by the name it was declared with in a producing step's artifacts block:

# A previous step that produces a named artifact: - step: name: Build artifacts: - name: production-build paths: - dist/** # The calling step can reference the named artifact: - step: name: Security Scan type: pipeline custom: security-scan artifacts: input: - production-build # references the artifact named above output: - security-report # child produces a named artifact called "security-report"

Missing Input Artifacts

If an artifact listed in artifacts: input: doesn't exist when the child is triggered — for example because a previous step was skipped — the child still runs. It simply doesn't have that file available. No error is thrown.

This allows child pipelines to handle optional inputs gracefully:

# In the child pipeline: - step: name: Compare Against Baseline script: - | if [ -f baseline-results.json ]; then echo "Comparing against previous baseline..." ./scripts/compare.sh baseline-results.json current-results.json else echo "No baseline provided — skipping comparison" fi

Complete Example

A parent pipeline that builds an application, then passes the build artifact into both a security scan child and a deployment child, receiving reports back from each:

image: node:20 pipelines: branches: main: # Step 1: Build — produces app.tar.gz - step: name: Build Application script: - npm ci - npm run build - tar -czf app.tar.gz dist/ artifacts: - app.tar.gz # Step 2: Security scan — receives build, returns report - step: name: Security Scan type: pipeline custom: security-scan artifacts: input: - app.tar.gz # push build artifact into child output: - security-report.json # pull scan results back to parent # Step 3: Deploy to staging — receives build, returns deployment info - step: name: Deploy to Staging type: pipeline custom: deploy-to-k8s input-variables: ENVIRONMENT: staging NAMESPACE: payments-staging artifacts: input: - app.tar.gz # same build artifact, passed to deploy child output: - deployment-report.json # deployment info returned to parent # Step 4: Notify — both reports are available in parent context - step: name: Notify Team script: - cat security-report.json - cat deployment-report.json - ./scripts/notify-slack.sh

Child pipeline (security-scan):

# org-pipelines/security-baseline.yml # No special declarations needed — just uses standard artifacts pipelines: custom: security-scan: - step: name: Scan Dependencies script: # app.tar.gz is available because the parent pushed it in - tar -xzf app.tar.gz - npm audit --audit-level=moderate - ./scripts/generate-security-report.sh > security-report.json artifacts: - security-report.json # parent will pull this back

Constraints

Constraint

Value

Constraint

Value

Artifact size limit

1 GB per artifact (same as standard artifacts)

Artifact retention

14 days

Step type required

type: pipeline

Contract defined on

Parent side only

Child declaration required

None


 

Still need help?

The Atlassian Community is here for you.