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 |
| String/number parameters |
File inputs |
| File/blob arguments |
Return values |
| 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 referenceStep Properties
Property | Required | Description |
|---|---|---|
| ✅ | Must be |
| ✅ | Name of the custom pipeline to run in the child |
| ❌ | Map of key/value pairs passed to the child (see Variable Sharing) |
| ❌ | Artifacts from the parent to push into the child before it runs |
| ❌ | 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.jsonBefore 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.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.
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.infoBy 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"
fiComplete 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.shChild 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 backConstraints
Constraint | Value |
|---|
Constraint | Value |
|---|---|
Artifact size limit | 1 GB per artifact (same as standard artifacts) |
Artifact retention | 14 days |
Step type required |
|
Contract defined on | Parent side only |
Child declaration required | None |
Related
Artifacts reference — Standard artifact configuration within a single pipeline
Variable sharing reference — Passing scalar values to child pipelines
Parent/Child pipelines reference — Core syntax and trigger modes
Was this helpful?