| name | create-pipeline-v1 |
| description | Generate Harness v1 simplified Pipeline YAML using the new concise syntax with flat structure, ${{ }} expressions, script field, and action steps. Supports CI stages (run, run-test, background), CD stages (service/environment with action steps for K8s, Helm, ECS), approval (stage-level and inline), parallel execution, matrix/for/while strategies, caching, volumes, and templates. Use when asked for a v1 pipeline, simplified pipeline, new pipeline format, or when user specifically requests v1 syntax. Do NOT use for v0/standard pipelines (use create-pipeline). Trigger phrases: v1 pipeline, simplified pipeline, new pipeline format, create v1, modern pipeline syntax. |
| metadata | {"author":"Harness","version":"3.1.0","mcp-server":"harness-mcp-v2"} |
| license | Apache-2.0 |
| compatibility | Requires Harness MCP v2 server (harness-mcp-v2) |
Create Pipeline v1
Generate Harness v1 simplified Pipeline YAML and optionally push to Harness via MCP.
Alpha: This skill is currently in internal testing only.
Instructions
- Confirm v1 format - User must specifically want v1 syntax. Default to v0 (
/create-pipeline) if unclear.
- Clarify requirements - Pipeline type (CI, CD, or both), language/framework, deployment target
- Consult the spec reference - Use
references/v1-spec-schema.md for the complete v1 schema, step types, action catalog, and examples
- Select native actions - Always prefer native action and template steps over
run: steps. Consult references/native-actions.md for the full mapping. Key rules:
- Docker build/push → use
template: uses: buildAndPushToDocker / buildAndPushToECR / buildAndPushToGAR (never run: docker build && docker push)
- K8s deploy → use
action: uses: kubernetes-rolling-deploy or template: uses: k8sRollingDeployStep (never run: kubectl apply)
- Helm deploy → use
action: uses: helm-deploy or template: uses: helmDeployBasicStep (never run: helm upgrade --install)
- ECS deploy → use
template: uses: ecsBluegreenDeployStep (never run: aws ecs update-service)
- Terraform → use
template: uses: terraformStep (never run: terraform apply)
- Security scanning → use native STO templates (
gitleaksStep, banditStep, sbomOrchestrationStep)
- Uploads → use
template: uses: uploadArtifactsToS3 / uploadArtifactsToGCS (never run: aws s3 cp)
- Approvals → use
approval: uses: harness or approval: uses: jira (never polling scripts)
- Ticketing → use
action: uses: jira-create / snow-create (never run: curl)
- HTTP requests → use
action: uses: http or template: uses: httpStep (never run: curl)
- Use
run: steps only for custom build/test/lint commands with no native equivalent
- Generate v1 YAML using flat structure,
${{ }} expressions, script field for run steps, and action/template steps for deployments
- Optionally create via MCP using
harness_create with resource_type: "pipeline_v1" (v1 pipelines are a distinct resource type from v0 pipeline)
v1 Key Differences from v0
| v0 Syntax | v1 Syntax |
|---|
<+variable> expressions | ${{ variable }} expressions |
type: CI / type: Deployment stage types | Flat stages -- no type field |
command: field in Run steps | script: field in run: steps |
Native steps (K8sRollingDeploy, HelmDeploy) | Action steps (action: uses: kubernetes-rolling-deploy) |
failureStrategies: | on-failure: |
HarnessApproval step type | approval: uses: harness (stage-level or inline) |
Deep nesting (spec: execution: steps:) | Flat structure (steps:) |
strategy: matrix: under stage spec | strategy: matrix: directly on stage or step |
Pipeline Structure
pipeline:
name: My Pipeline
repo:
connector: account.github
name: myorg/my-repo
clone:
depth: 1
on:
- push:
branches: [main]
env:
NODE_ENV: production
inputs:
branch:
type: string
default: main
stages:
- name: build
steps:
- run:
script: go build
No version:, kind:, or spec: wrapper -- pipeline: is the root key.
Stages
Stages have no type field. Their purpose is determined by their keys.
CI Stage
- name: build
runtime: cloud
platform:
os: linux
arch: arm
cache:
path: node_modules
key: npm.${{ branch }}
steps:
- run:
script: npm ci
Deployment Stage
- name: deploy
service: my-service
environment: staging
steps:
- action:
uses: kubernetes-rolling-deploy
with:
dry-run: false
Approval (stage-level)
- approval:
uses: harness
with:
timeout: 30m
message: "Approve deployment?"
groups: [admins, ops]
min-approvers: 1
Step Types
Run Step
Uses script: field (not command: or run:).
- run:
script: npm test
- run: npm test
- run:
container: node:18
script: npm test
- run:
shell: bash
script: |
npm ci
npm test
env:
NODE_ENV: test
- id: build
run:
script: echo "TAG=v1" >> $HARNESS_OUTPUT
output: [TAG]
Run Test Step
- run-test:
container: maven
script: mvn test
report:
type: junit
path: target/surefire-reports/*.xml
splitting:
concurrency: 4
Action Step
Actions replace v0 native steps. See references/v1-spec-schema.md for the full action catalog.
- action:
uses: kubernetes-rolling-deploy
with:
dry-run: false
- action:
uses: helm-deploy
with:
timeout: 10m
- action:
uses: terraform-plan
with:
command: apply
aws-provider: account.aws_connector
- action:
uses: http
with:
method: GET
endpoint: https://acme.com
Background Step
- background:
container: redis
- run:
script: npm test
Template Step
- template:
uses: account.docker@1.0.0
with:
push: true
tags: latest
Approval Step (inline)
- approval:
uses: jira
with:
connector: account.jira
project: PROJ
Parallel and Group
- parallel:
steps:
- run:
script: npm run lint
- run:
script: npm test
- parallel:
stages:
- steps:
- run: go test
- steps:
- run: npm test
- group:
steps:
- run:
script: go build
- run:
script: go test
Strategy
- strategy:
matrix:
node: [16, 18, 20]
os: [linux, macos]
max-parallel: 3
steps:
- run:
container: node:${{ matrix.node }}
script: npm test
- strategy:
matrix:
go: [1.19, 1.20, 1.21]
run:
container: golang:${{ matrix.go }}
script: go test
Failure Strategy
- run:
script: go test
on-failure:
errors: all
action: ignore
- run:
script: go test
on-failure:
errors: [unknown]
action:
retry:
attempts: 5
interval: 10s
failure-action: fail
- steps:
- run:
script: go test
on-failure:
errors: all
action: abort
Conditional Execution
- if: ${{ branch == "main" }}
steps:
- run:
script: deploy.sh
- if: ${{ branch == "main" }}
run:
script: deploy.sh
Complete CI Example
pipeline:
repo:
connector: account.github
name: myorg/my-app
clone:
depth: 1
on:
- push:
branches: [main]
- pull_request:
branches: [main]
stages:
- name: build-and-test
runtime: cloud
platform:
os: linux
arch: arm
cache:
path: node_modules
key: npm.${{ branch }}
steps:
- run:
script: npm ci
- parallel:
steps:
- run:
script: npm run lint
- run-test:
script: npm test
report:
type: junit
path: junit.xml
- action:
uses: docker-build-push
with:
connector: dockerhub
repo: myorg/my-app
tags: [${{ pipeline.sequenceId }}, latest]
Complete CD Example
pipeline:
inputs:
skip_dry_run:
type: boolean
default: false
stages:
- name: deploy-staging
service: petstore
environment: staging
steps:
- action:
uses: manifest-download
- action:
uses: manifest-bake
- action:
uses: kubernetes-rolling-deploy
with:
dry-run: ${{ inputs.skip_dry_run }}
- approval:
uses: harness
with:
timeout: 1d
message: "Approve production deployment?"
groups: [prod-approvers]
min-approvers: 1
- name: deploy-prod
service: petstore
environment: prod
steps:
- action:
uses: manifest-download
- action:
uses: manifest-bake
- action:
uses: kubernetes-rolling-deploy
with:
dry-run: false
Creating via MCP
- Verify the project exists — List projects with
harness_list (resource_type: project, org_id) to confirm. If the project does not exist, create it first with harness_create (resource_type: project, body: { identifier, name }) or ask the user.
- Create the pipeline — Use
harness_create with resource_type: "pipeline_v1" (v1 is a distinct resource type from v0 pipeline). Serialize the v1 YAML as a yamlPipeline string in the body or pass the raw YAML string directly. Do not pass a nested JSON pipeline object; it causes serialization errors.
Call MCP tool: harness_create
Parameters:
resource_type: "pipeline_v1"
org_id: "<organization>"
project_id: "<project>"
body: { yamlPipeline: "<full v1 pipeline YAML string, including 'pipeline:' root key>" }
Alternatively you can pass the body as a raw YAML string: body: "pipeline:\n name: ...\n stages: ...".
Examples
Create a v1 CI pipeline
/create-pipeline-v1
Create a v1 CI pipeline for a Node.js app with caching, parallel lint and test, and Docker push
Create a v1 deployment pipeline
/create-pipeline-v1
Create a v1 Kubernetes deployment pipeline with staging approval and production stages
Create a v1 matrix build
/create-pipeline-v1
Create a v1 pipeline that tests across Go 1.19, 1.20, and 1.21 using matrix strategy
Performance Notes
- Always check
references/native-actions.md before using a run: step. Native actions provide better error handling, rollback support, and UI integration.
- Always consult
references/v1-spec-schema.md for the complete v1 spec before generating YAML.
- Use
script: field in run steps, never command: or run: as the field name.
- Use
action: uses: or template: uses: for deployments, never v0 native step types like K8sRollingDeploy.
- Do not mix v0 and v1 syntax. No
<+...> expressions, no type: on stages, no spec: wrapper.
- Validate all expressions use
${{ }} syntax before presenting.
Troubleshooting
Common v1 Syntax Errors
- Using
<+...> instead of ${{ ... }} expressions
- Adding
type: field on stages (v1 stages have no type)
- Using
command: or run: as the field name instead of script:
- Wrapping pipeline in
version:, kind:, spec: (v1 uses bare pipeline:)
- Using v0 step types (
K8sRollingDeploy) instead of actions (action: uses: kubernetes-rolling-deploy)
- Using
failureStrategies: instead of on-failure:
MCP Errors
- Project not found — Verify the project exists with
harness_list (resource_type: project, org_id). Create it first or confirm org_id/project_id are correct.
- Wrong resource type — v1 pipelines use
resource_type: "pipeline_v1", not "pipeline". The v0 pipeline resource type will reject v1 YAML.
- Missing required fields for pipeline: pipeline — Pass the body as
{ yamlPipeline: "<full v1 pipeline YAML string>" }, a raw YAML string, or { pipeline: {...} }. Do not mix shapes.
DUPLICATE_IDENTIFIER — Pipeline exists; use harness_update with the same resource_type: "pipeline_v1".
INVALID_REQUEST — Check YAML structure matches v1 schema. Use harness_schema(resource_type="pipeline_v1") for the authoritative body schema.