Your First Pipeline
This walkthrough builds a complete DevRamps pipeline for a Node.js application deployed to Amazon ECS, with Terraform-managed infrastructure.
This example references Terraform outputs like ecs_cluster_name and task_definition_arn. Your Terraform configuration in the infrastructure/ directory must define the ECS cluster, service, task definition, and related resources, and expose them as Terraform outputs. DevRamps does not create this infrastructure for you — Terraform does, as part of the pipeline.
By the end, you'll have a pipeline that:
- Builds a Docker image from your application source.
- Runs Terraform to provision infrastructure.
- Deploys the container to ECS with rolling updates.
- Waits for a bake period after deployment.
- Deploys to staging first, then promotes to production.
Project Structure
Assume your repository looks like this:
my-app/
├── .devramps/
│ └── my-app/
│ └── pipeline.yaml # Pipeline definition
├── infrastructure/
│ ├── main.tf # Terraform configuration
│ ├── variables.tf
│ └── outputs.tf
├── src/
│ └── ... # Application source code
├── Dockerfile
└── package.json
Step 1: Define Your Stages
Start with two stages: staging and production. Each stage targets a different AWS account.
version: "1.0.0"
pipeline:
cloud_provider: AWS
pipeline_updates_require_approval: ALWAYS
stage_defaults:
deployment_time_window: PACIFIC_WORKING_HOURS
stages:
- name: staging
deployment_time_window: NONE
account_id: "111111111111"
region: us-east-1
vars:
env: staging
service_name: my-app
- name: production
account_id: "222222222222"
region: us-east-1
vars:
env: production
service_name: my-app
A few things to note:
pipeline_updates_require_approval: ALWAYSmeans changes to your pipeline definition will require approval before taking effect.stage_defaultssetsPACIFIC_WORKING_HOURSas the default deployment window for all stages. Staging overrides this toNONEso deployments can happen anytime.varsdefines stage-specific variables that you can reference in your steps using${{ vars.env }}.
Step 2: Define Your Artifacts
Your pipeline needs a Docker image. Define it in the artifacts section:
artifacts:
App Image:
type: DEVRAMPS:DOCKER:BUILD
rebuild_when_changed:
- /src
- /Dockerfile
- /package.json
params:
dockerfile: /Dockerfile
rebuild_when_changedtells DevRamps to only rebuild the image when files in these paths change. If you push a change that only touches your Terraform files, the image won't be rebuilt.- The artifact name (
App Image) is how you reference it from your steps.
Step 3: Define Your Steps
Now define the deployment steps that run in each stage:
steps:
- name: Synthesize Infrastructure
id: infra
type: DEVRAMPS:TERRAFORM:SYNTHESIZE
params:
requires_approval: DESTRUCTIVE_CHANGES_ONLY
source: /infrastructure
variables:
environment: ${{ vars.env }}
region: ${{ stage.region }}
aws_account_id: ${{ stage.account_id }}
service_name: ${{ vars.service_name }}
image_url: ${{ stage.artifacts["App Image"].image_url }}
- name: Deploy to ECS
type: DEVRAMPS:ECS:DEPLOY
goes_after: ["Synthesize Infrastructure"]
params:
cluster_name: ${{ steps.infra.ecs_cluster_name }}
service_name: ${{ steps.infra.ecs_service_name }}
reference_task_definition: ${{ steps.infra.task_definition_arn }}
image_url: ${{ stage.artifacts["App Image"].image_url }}
- name: Bake Period
type: DEVRAMPS:APPROVAL:BAKE
params:
duration_minutes: 5
Key details:
- The
id: infrafield gives the Terraform step a short alias for use in expressions. Instead of${{ steps["Synthesize Infrastructure"].ecs_cluster_name }}, you can write${{ steps.infra.ecs_cluster_name }}. goes_afterexplicitly controls step ordering. By default, steps run sequentially in the order listed. Usinggoes_afteris useful when you want to run steps in parallel — steps withoutgoes_afterthat are listed after agoes_afterstep won't wait for it. Here,Deploy to ECSexplicitly depends on Terraform finishing first because it needs the Terraform outputs.requires_approval: DESTRUCTIVE_CHANGES_ONLYmeans Terraform changes that destroy resources will pause for your review, while non-destructive changes apply automatically.- The
Bake Periodstep waits 5 minutes after deployment, giving you time to verify the deployment is healthy before promoting to the next stage.
Step 4: Add Secrets (Optional)
If your Terraform configuration needs secrets (e.g., an API key), add them in the DevRamps dashboard:
- Go to your organization settings.
- Navigate to Secrets.
- Add a secret with a name like
DATABASE_PASSWORD. - Optionally scope it to a specific stage.
Then reference it in your pipeline:
variables:
db_password: ${{ organization.secrets["DATABASE_PASSWORD"] }}
# or for a stage-scoped secret:
db_password: ${{ stage.secrets["DB_PASSWORD"] }}
Secrets are never exposed in logs or the UI -- they're injected at runtime just before the step executes.
The Complete Pipeline
Here's the full pipeline.yaml:
version: "1.0.0"
pipeline:
cloud_provider: AWS
pipeline_updates_require_approval: ALWAYS
stage_defaults:
deployment_time_window: PACIFIC_WORKING_HOURS
stages:
- name: staging
deployment_time_window: NONE
account_id: "111111111111"
region: us-east-1
vars:
env: staging
service_name: my-app
- name: production
account_id: "222222222222"
region: us-east-1
vars:
env: production
service_name: my-app
steps:
- name: Synthesize Infrastructure
id: infra
type: DEVRAMPS:TERRAFORM:SYNTHESIZE
params:
requires_approval: DESTRUCTIVE_CHANGES_ONLY
source: /infrastructure
variables:
environment: ${{ vars.env }}
region: ${{ stage.region }}
aws_account_id: ${{ stage.account_id }}
service_name: ${{ vars.service_name }}
image_url: ${{ stage.artifacts["App Image"].image_url }}
- name: Deploy to ECS
type: DEVRAMPS:ECS:DEPLOY
goes_after: ["Synthesize Infrastructure"]
params:
cluster_name: ${{ steps.infra.ecs_cluster_name }}
service_name: ${{ steps.infra.ecs_service_name }}
reference_task_definition: ${{ steps.infra.task_definition_arn }}
image_url: ${{ stage.artifacts["App Image"].image_url }}
- name: Bake Period
type: DEVRAMPS:APPROVAL:BAKE
params:
duration_minutes: 5
artifacts:
App Image:
type: DEVRAMPS:DOCKER:BUILD
rebuild_when_changed:
- /src
- /Dockerfile
- /package.json
params:
dockerfile: /Dockerfile
About Terraform State
DevRamps automatically manages your Terraform state. State files are stored in an S3 bucket in your CI/CD account, and DevRamps configures the backend for you — you don't need to add a backend block to your Terraform configuration.
About Terraform Outputs
All outputs defined in your Terraform configuration automatically become available as step outputs. For example, if your Terraform has output "ecs_cluster_name" { value = aws_ecs_cluster.main.name }, you can reference it as ${{ steps.infra.ecs_cluster_name }} in subsequent steps.
Deploying
- Bootstrap: Run
npx @devramps/cli bootstrap --dry-runfirst to preview, thennpx @devramps/cli bootstrapto create IAM roles in both AWS accounts. - Push: Commit and push your pipeline definition. DevRamps creates the pipeline and starts the first deployment.
- Monitor: Watch the deployment in the DevRamps dashboard. You'll see:
- Artifact builds (the Docker image being constructed).
- Staging steps executing (Terraform plan → apply → ECS deploy → bake).
- Automatic promotion to production after staging succeeds.
What Happens When Something Fails?
If a step fails during deployment:
- The deployment stops at the failed step. No further steps run in that stage.
- The next stage does not start.
- You can view the step logs in the dashboard to understand what went wrong.
- Use the AI Failure Analysis feature to get an automated root cause analysis and suggested fix.
- Once you've fixed the issue, push the fix and DevRamps starts a new deployment. Or retry the failed stage to re-run with the same code.
Next Steps
- Pipeline Configuration -- Deep dive into all pipeline YAML options.
- Step Reference -- Browse all available step types.
- Managing Deployments -- Learn about rollback, retry, and cancellation.