Skip to main content
OCIDevOps & IaCintermediate

OCI DevOps CI/CD

Build end-to-end CI/CD pipelines with OCI DevOps build pipelines, deployment pipelines, code repositories, and artifact registry.

CloudToolStack Team24 min readPublished Mar 14, 2026

Prerequisites

  • OCI account with DevOps service permissions
  • Basic understanding of CI/CD concepts and Docker

Introduction to OCI DevOps

OCI DevOps is a fully managed, end-to-end continuous integration and continuous delivery (CI/CD) platform built into Oracle Cloud Infrastructure. It provides build pipelines for compiling, testing, and packaging applications; deployment pipelines for rolling out changes to OKE clusters, compute instances, and Functions; and an integrated artifact registry for storing container images, generic artifacts, and deployment manifests.

Unlike third-party CI/CD tools that require separate infrastructure and authentication setup, OCI DevOps is natively integrated with OCI IAM policies, networking, and resource management. Build runners execute in your tenancy with access to private OCI resources through service gateways, and deployment pipelines can target any OCI compute resource directly. This tight integration eliminates the need for long-lived credentials or complex network configurations between your CI/CD system and your cloud infrastructure.

This guide walks you through the complete OCI DevOps workflow: creating a project, configuring code repositories, building container images with build pipelines, storing artifacts, and deploying to OKE and compute instances with deployment pipelines. Every step includes CLI commands and configuration examples you can adapt for your own applications.

OCI DevOps Pricing

OCI DevOps has no additional service charges. You pay only for the underlying compute used by build runners and deployment targets. Build pipelines use managed build runners with shapes you select (default is 1 OCPU, 8 GB memory). Build time is billed per minute of compute usage. Artifact Registry storage is charged at standard Object Storage rates. The OCI Code Repository (managed Git) is free with no storage limits for private repositories.

Setting Up a DevOps Project

A DevOps project is the top-level container for all CI/CD resources including code repositories, build pipelines, artifacts, deployment pipelines, and environments. Each project maps to one application or microservice, though you can organize multiple related services under a single project with separate pipelines.

Required IAM Policies

bash
# Create a dynamic group for DevOps resources
oci iam dynamic-group create \
  --name DevOpsResources \
  --description "Dynamic group for OCI DevOps build and deploy resources" \
  --matching-rule "ANY {resource.type = 'devopsbuildpipeline', resource.type = 'devopsdeploypipeline', resource.type = 'devopsrepository', resource.type = 'devopsconnection'}"

# Policies for DevOps service to manage resources
oci iam policy create \
  --compartment-id <tenancy-ocid> \
  --name DevOpsPolicy \
  --description "Policies for OCI DevOps service" \
  --statements '[
    "Allow dynamic-group DevOpsResources to manage repos in compartment devops",
    "Allow dynamic-group DevOpsResources to manage generic-artifacts in compartment devops",
    "Allow dynamic-group DevOpsResources to use ons-topics in compartment devops",
    "Allow dynamic-group DevOpsResources to read all-artifacts in compartment devops",
    "Allow dynamic-group DevOpsResources to manage devops-family in compartment devops",
    "Allow dynamic-group DevOpsResources to manage cluster-family in compartment devops",
    "Allow dynamic-group DevOpsResources to manage instance-agent-command-family in compartment devops",
    "Allow dynamic-group DevOpsResources to read instance-family in compartment devops",
    "Allow dynamic-group DevOpsResources to manage compute-management-family in compartment devops"
  ]'

# Policy for developers to use DevOps
oci iam policy create \
  --compartment-id <tenancy-ocid> \
  --name DevelopersDevOps \
  --description "Allow developers to use OCI DevOps" \
  --statements '[
    "Allow group Developers to manage devops-family in compartment devops",
    "Allow group Developers to manage repos in compartment devops",
    "Allow group Developers to read all-artifacts in compartment devops"
  ]'

Creating the Project

bash
# Create a notification topic for build/deploy events
oci ons topic create \
  --compartment-id <compartment-ocid> \
  --name "devops-notifications" \
  --description "Notifications for DevOps pipeline events"

# Create the DevOps project
oci devops project create \
  --compartment-id <compartment-ocid> \
  --name "ecommerce-api" \
  --description "CI/CD for the ecommerce API microservice" \
  --notification-config '{"topicId": "<topic-ocid>"}'

# Verify the project was created
oci devops project list \
  --compartment-id <compartment-ocid> \
  --query 'data.items[].{"Name": name, "ID": id, "State": "lifecycle-state"}' \
  --output table

Code Repositories

OCI DevOps includes a managed Git hosting service called OCI Code Repository. It provides private Git repositories with branch protection, mirroring from external Git providers, and integration with build pipelines for automatic trigger on push. You can also connect external repositories from GitHub, GitLab, or Bitbucket Cloud using external connections.

bash
# Create a code repository
oci devops repository create \
  --project-id <project-ocid> \
  --name "ecommerce-api" \
  --description "Source code for the ecommerce API" \
  --repository-type HOSTED \
  --default-branch "refs/heads/main"

# Get the HTTPS clone URL
oci devops repository get \
  --repository-id <repo-ocid> \
  --query 'data.{"Clone URL": "http-url", "SSH URL": "ssh-url"}' \
  --output table

# Clone and push your code
git clone <https-clone-url> ecommerce-api
cd ecommerce-api

# Add your application code
# ... (create your app files)

git add .
git commit -m "Initial commit"
git push origin main

# Create an external connection to GitHub (alternative)
oci devops connection create-github-access-token-connection \
  --project-id <project-ocid> \
  --display-name "github-connection" \
  --access-token "<vault-secret-ocid-containing-github-pat>"

# Mirror an external GitHub repo
oci devops repository create \
  --project-id <project-ocid> \
  --name "ecommerce-api-mirror" \
  --repository-type MIRRORED \
  --mirror-repository-config '{
    "connectorId": "<connection-ocid>",
    "repositoryUrl": "https://github.com/myorg/ecommerce-api.git",
    "mirrorScheduleType": "DEFAULT"
  }'

External Connections

If your code already lives in GitHub, GitLab, or Bitbucket Cloud, use an external connection rather than migrating to OCI Code Repository. Store your personal access token in OCI Vault and reference the secret OCID in the connection configuration. Build pipelines can trigger on push events from external repositories through webhook integration.

Build Pipelines

Build pipelines define the steps to compile, test, package, and publish your application. Each pipeline consists of stages that execute sequentially or in parallel. The most common stage types are Managed Build (runs your build commands on an OCI-managed runner), Deliver Artifacts (pushes build outputs to the Artifact Registry or Container Registry), and Trigger Deployment (starts a deployment pipeline on successful build).

Build specifications are defined in a build_spec.yaml file at the root of your repository. This file describes the build steps, environment variables, exported variables, and output artifacts.

yaml
# build_spec.yaml - placed in the root of your repository
version: 0.1
component: build
timeoutInSeconds: 600
runAs: root
shell: bash

env:
  variables:
    APP_NAME: "ecommerce-api"
    JAVA_HOME: "/usr/lib64/graalvm/graalvm-java17"
  exportedVariables:
    - IMAGE_TAG
    - BUILD_HASH

steps:
  - type: Command
    name: "Set Build Variables"
    command: |
      export IMAGE_TAG=${OCI_BUILD_RUN_ID::8}
      export BUILD_HASH=$(git rev-parse --short HEAD)
      echo "Building image tag: ${IMAGE_TAG}"

  - type: Command
    name: "Run Unit Tests"
    command: |
      mvn test -B -q
    onFailure:
      - type: Command
        command: |
          echo "Unit tests failed!"
          cat target/surefire-reports/*.txt

  - type: Command
    name: "Build Application"
    command: |
      mvn package -DskipTests -B -q
      echo "Build complete: target/${APP_NAME}.jar"

  - type: Command
    name: "Build Container Image"
    command: |
      docker build \
        --build-arg JAR_FILE=target/${APP_NAME}.jar \
        --tag ecommerce-api:${IMAGE_TAG} \
        --tag ecommerce-api:latest \
        .

outputArtifacts:
  - name: ecommerce-api-image
    type: DOCKER_IMAGE
    location: ecommerce-api:${IMAGE_TAG}

  - name: deployment-manifest
    type: BINARY
    location: ${OCI_WORKSPACE_DIR}/deploy/k8s-manifest.yaml

Creating the Build Pipeline

bash
# Create the build pipeline
oci devops build-pipeline create \
  --project-id <project-ocid> \
  --display-name "ecommerce-api-build" \
  --description "Build, test, and package the ecommerce API"

# Add a Managed Build stage
oci devops build-pipeline-stage create-managed-build-stage \
  --build-pipeline-id <build-pipeline-ocid> \
  --display-name "Build and Test" \
  --description "Run tests, build JAR, create Docker image" \
  --build-spec-file "build_spec.yaml" \
  --stage-execution-timeout-in-seconds 600 \
  --build-runner-shape-config '{"buildRunnerType": "DEFAULT", "ocpus": 2, "memoryInGBs": 16}' \
  --primary-build-source '{
    "connectionType": "DEVOPS_CODE_REPOSITORY",
    "repositoryId": "<repo-ocid>",
    "name": "primary",
    "branch": "main"
  }' \
  --build-pipeline-stage-predecessor-collection '{"items": [{"id": "<build-pipeline-ocid>"}]}'

# Add a Deliver Artifacts stage
oci devops build-pipeline-stage create-deliver-artifact-stage \
  --build-pipeline-id <build-pipeline-ocid> \
  --display-name "Push Artifacts" \
  --description "Push container image and deployment manifest" \
  --deliver-artifact-collection '{
    "items": [
      {
        "artifactName": "ecommerce-api-image",
        "artifactId": "<container-image-artifact-ocid>"
      },
      {
        "artifactName": "deployment-manifest",
        "artifactId": "<generic-artifact-ocid>"
      }
    ]
  }' \
  --build-pipeline-stage-predecessor-collection '{"items": [{"id": "<build-stage-ocid>"}]}'

# Manually trigger a build run
oci devops build-run create \
  --build-pipeline-id <build-pipeline-ocid> \
  --display-name "manual-build-001"

# Check build run status
oci devops build-run get \
  --build-run-id <build-run-ocid> \
  --query 'data.{"Status": "lifecycle-state", "Started": "time-created", "Stages": "build-run-progress.build-pipeline-stage-run-progress"}' \
  --output table

Artifact Registry

The OCI Artifact Registry stores build outputs including container images, generic artifacts (JARs, ZIPs, Helm charts), and deployment manifests. It integrates with both build pipelines and deployment pipelines, serving as the bridge between the two. Container images are stored in the OCI Container Registry (OCIR), while generic artifacts use the Artifact Registry service.

bash
# Create a container repository for Docker images
oci artifacts container repository create \
  --compartment-id <compartment-ocid> \
  --display-name "ecommerce-api" \
  --is-public false \
  --is-immutable false

# Create an artifact repository for generic artifacts
oci artifacts repository create \
  --compartment-id <compartment-ocid> \
  --display-name "ecommerce-artifacts" \
  --repository-type GENERIC \
  --is-immutable false

# Push a container image manually (for testing)
docker login <region-key>.ocir.io -u '<tenancy-namespace>/oracleidentitycloudservice/<email>'
docker tag ecommerce-api:latest <region-key>.ocir.io/<tenancy-namespace>/ecommerce-api:latest
docker push <region-key>.ocir.io/<tenancy-namespace>/ecommerce-api:latest

# Upload a generic artifact via CLI
oci artifacts generic artifact upload-by-path \
  --repository-id <artifact-repo-ocid> \
  --artifact-path "ecommerce-api/deploy/k8s-manifest.yaml" \
  --artifact-version "1.0.0" \
  --content-body k8s-manifest.yaml

# List artifacts in a repository
oci artifacts generic artifact list \
  --compartment-id <compartment-ocid> \
  --repository-id <artifact-repo-ocid> \
  --query 'data.items[].{"Path": "artifact-path", "Version": version, "State": "lifecycle-state"}' \
  --output table

# Define artifacts in the DevOps project for pipeline references
oci devops deploy-artifact create \
  --project-id <project-ocid> \
  --display-name "ecommerce-api-image" \
  --deploy-artifact-type DOCKER_IMAGE \
  --argument-substitution-mode SUBSTITUTE_PLACEHOLDERS \
  --deploy-artifact-source '{
    "deployArtifactSourceType": "OCIR",
    "imageUri": "<region-key>.ocir.io/<namespace>/ecommerce-api:${IMAGE_TAG}",
    "imageDigest": ""
  }'

Image Retention Policies

Container repositories accumulate images quickly in active CI/CD pipelines. Configure retention policies to automatically delete images older than a specified number of days or to keep only the N most recent versions. Without retention policies, storage costs grow linearly with every build. Set is-immutable to true for production repositories to prevent accidental overwrites of released versions.

Deployment Pipelines

Deployment pipelines orchestrate the rollout of artifacts to target environments. OCI DevOps supports several deployment strategies including rolling deployments (update instances or pods in batches), blue-green deployments (shift traffic between two identical environments), and canary deployments (route a percentage of traffic to the new version). Deployments can target OKE clusters, instance groups, or OCI Functions.

Deploying to OKE (Kubernetes)

bash
# Create an OKE environment
oci devops deploy-environment create-oke-cluster-environment \
  --project-id <project-ocid> \
  --display-name "production-oke" \
  --description "Production OKE cluster" \
  --cluster-id <oke-cluster-ocid>

# Create a deployment pipeline
oci devops deploy-pipeline create \
  --project-id <project-ocid> \
  --display-name "ecommerce-api-deploy" \
  --description "Deploy ecommerce API to OKE"

# Add a rolling deployment stage to OKE
oci devops deploy-stage create-oke-deploy-stage \
  --deploy-pipeline-id <deploy-pipeline-ocid> \
  --display-name "Rolling Deploy to OKE" \
  --oke-cluster-deploy-environment-id <oke-env-ocid> \
  --kubernetes-manifest-deploy-artifact-ids '["<k8s-manifest-artifact-ocid>"]' \
  --rollback-policy '{"policyType": "AUTOMATED_STAGE_ROLLBACK_POLICY"}' \
  --deploy-stage-predecessor-collection '{"items": [{"id": "<deploy-pipeline-ocid>"}]}'

# Add an approval stage before production deployment
oci devops deploy-stage create-manual-approval-stage \
  --deploy-pipeline-id <deploy-pipeline-ocid> \
  --display-name "Production Approval" \
  --approval-policy '{"approvalPolicyType": "COUNT_BASED_APPROVAL", "numberOfApprovalsRequired": 1}' \
  --deploy-stage-predecessor-collection '{"items": [{"id": "<deploy-pipeline-ocid>"}]}'

Kubernetes Manifest with Variable Substitution

yaml
# k8s-manifest.yaml - uses OCI DevOps variable substitution
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ecommerce-api
  namespace: production
  labels:
    app: ecommerce-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: ecommerce-api
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    metadata:
      labels:
        app: ecommerce-api
        version: ${IMAGE_TAG}
    spec:
      containers:
        - name: ecommerce-api
          image: ${OCIR_REGION}.ocir.io/${OCIR_NAMESPACE}/ecommerce-api:${IMAGE_TAG}
          ports:
            - containerPort: 8080
          resources:
            requests:
              cpu: "500m"
              memory: "512Mi"
            limits:
              cpu: "1000m"
              memory: "1Gi"
          readinessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 10
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /health
              port: 8080
            initialDelaySeconds: 30
            periodSeconds: 10
      imagePullSecrets:
        - name: ocir-secret
---
apiVersion: v1
kind: Service
metadata:
  name: ecommerce-api-svc
  namespace: production
spec:
  type: LoadBalancer
  selector:
    app: ecommerce-api
  ports:
    - port: 80
      targetPort: 8080
      protocol: TCP

Deploying to Compute Instances

For applications running on OCI Compute instances (VMs or bare metal) rather than Kubernetes, OCI DevOps provides instance group deployments. You define an instance group environment that references a set of compute instances, then create deployment stages that execute shell commands or deploy artifacts to those instances in a rolling fashion.

bash
# Create an instance group environment
oci devops deploy-environment create-compute-instance-group-environment \
  --project-id <project-ocid> \
  --display-name "api-servers" \
  --description "Production API server instances" \
  --compute-instance-group-selectors '{
    "items": [{
      "selectorType": "INSTANCE_QUERY",
      "region": "us-ashburn-1",
      "query": "any {instance.compartment.id = \u0027<compartment-ocid>\u0027, tag.app.value = \u0027ecommerce-api\u0027}"
    }]
  }'

# Create a deployment specification artifact
# deploy_spec.yaml defines commands to run on each instance
oci devops deploy-artifact create \
  --project-id <project-ocid> \
  --display-name "deploy-spec" \
  --deploy-artifact-type DEPLOYMENT_SPEC \
  --argument-substitution-mode SUBSTITUTE_PLACEHOLDERS \
  --deploy-artifact-source '{
    "deployArtifactSourceType": "INLINE",
    "base64EncodedContent": "<base64-encoded-deploy-spec>"
  }'
yaml
# deploy_spec.yaml - commands run on each instance
version: 1.0
component: deployment
files:
  - source: /
    destination: /opt/ecommerce-api
steps:
  - stepType: Command
    name: "Stop Service"
    command: sudo systemctl stop ecommerce-api
    timeoutInSeconds: 30
    runAs: root

  - stepType: Command
    name: "Deploy New Version"
    command: |
      cp /opt/ecommerce-api/ecommerce-api.jar /opt/ecommerce-api/ecommerce-api-backup.jar
      mv /opt/ecommerce-api/artifacts/ecommerce-api.jar /opt/ecommerce-api/ecommerce-api.jar
      chown app:app /opt/ecommerce-api/ecommerce-api.jar
    runAs: root

  - stepType: Command
    name: "Start Service"
    command: sudo systemctl start ecommerce-api
    timeoutInSeconds: 60
    runAs: root

  - stepType: Command
    name: "Health Check"
    command: |
      for i in {1..30}; do
        if curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/health | grep -q "200"; then
          echo "Service is healthy"
          exit 0
        fi
        sleep 2
      done
      echo "Health check failed"
      exit 1
    timeoutInSeconds: 120
    runAs: opc

Build Triggers

Build triggers automatically start build pipelines in response to code events like pushes to specific branches, pull request creation, or tag creation. This is the glue that enables continuous integration: every code change automatically triggers a build, runs tests, and optionally starts a deployment.

bash
# Create a trigger for pushes to main branch
oci devops trigger create-devops-code-repo-trigger \
  --project-id <project-ocid> \
  --display-name "main-branch-trigger" \
  --description "Trigger build on push to main" \
  --repository-id <repo-ocid> \
  --actions '[{
    "type": "TRIGGER_BUILD_PIPELINE",
    "buildPipelineId": "<build-pipeline-ocid>",
    "filter": {
      "triggerSource": "DEVOPS_CODE_REPOSITORY",
      "events": ["PUSH"],
      "include": {
        "headRef": "refs/heads/main"
      }
    }
  }]'

# Create a trigger for pull requests (run tests only)
oci devops trigger create-devops-code-repo-trigger \
  --project-id <project-ocid> \
  --display-name "pr-trigger" \
  --description "Trigger test pipeline on PR" \
  --repository-id <repo-ocid> \
  --actions '[{
    "type": "TRIGGER_BUILD_PIPELINE",
    "buildPipelineId": "<test-pipeline-ocid>",
    "filter": {
      "triggerSource": "DEVOPS_CODE_REPOSITORY",
      "events": ["PULL_REQUEST_CREATED", "PULL_REQUEST_UPDATED"],
      "include": {
        "baseRef": "refs/heads/main"
      }
    }
  }]'

# Create a trigger from external GitHub repository
oci devops trigger create-github-trigger \
  --project-id <project-ocid> \
  --display-name "github-main-trigger" \
  --connection-id <github-connection-ocid> \
  --actions '[{
    "type": "TRIGGER_BUILD_PIPELINE",
    "buildPipelineId": "<build-pipeline-ocid>",
    "filter": {
      "triggerSource": "GITHUB",
      "events": ["PUSH"],
      "include": {
        "headRef": "refs/heads/main"
      }
    }
  }]'

Connecting Build to Deploy

To create a fully automated CI/CD pipeline, add a "Trigger Deployment" stage as the last stage of your build pipeline. This stage automatically starts a deployment pipeline run with the artifacts produced by the build. You can pass build-time variables (like the image tag) to the deployment pipeline as parameters, enabling the deployment to use the exact artifact version that was just built.

Blue-Green and Canary Deployments

For zero-downtime deployments with automatic rollback capability, OCI DevOps supports blue-green and canary deployment strategies for OKE targets. Blue-green deployments maintain two identical environments and switch traffic atomically. Canary deployments gradually shift traffic to the new version while monitoring for errors.

bash
# Blue-Green deployment stage for OKE
oci devops deploy-stage create-oke-blue-green-deploy-stage \
  --deploy-pipeline-id <deploy-pipeline-ocid> \
  --display-name "Blue-Green Deploy" \
  --oke-cluster-deploy-environment-id <oke-env-ocid> \
  --kubernetes-manifest-deploy-artifact-ids '["<manifest-ocid>"]' \
  --deploy-stage-predecessor-collection '{"items": [{"id": "<deploy-pipeline-ocid>"}]}'

# Add a traffic shift stage (switches from blue to green)
oci devops deploy-stage create-oke-blue-green-traffic-shift-stage \
  --deploy-pipeline-id <deploy-pipeline-ocid> \
  --display-name "Shift Traffic" \
  --oke-blue-green-deploy-stage-id <blue-green-stage-ocid> \
  --deploy-stage-predecessor-collection '{"items": [{"id": "<blue-green-stage-ocid>"}]}'

# Canary deployment - deploy to a subset first
oci devops deploy-stage create-oke-canary-deploy-stage \
  --deploy-pipeline-id <deploy-pipeline-ocid> \
  --display-name "Canary Deploy (10%)" \
  --oke-cluster-deploy-environment-id <oke-env-ocid> \
  --kubernetes-manifest-deploy-artifact-ids '["<manifest-ocid>"]' \
  --deploy-stage-predecessor-collection '{"items": [{"id": "<deploy-pipeline-ocid>"}]}'

# Canary traffic shift - gradually increase traffic
oci devops deploy-stage create-oke-canary-traffic-shift-stage \
  --deploy-pipeline-id <deploy-pipeline-ocid> \
  --display-name "Canary Traffic 25%" \
  --oke-canary-deploy-stage-id <canary-stage-ocid> \
  --rollout-policy '{"batchCount": 4, "batchDelayInSeconds": 60, "rampLimitPercent": 25.0}' \
  --deploy-stage-predecessor-collection '{"items": [{"id": "<canary-stage-ocid>"}]}'

Monitoring and Troubleshooting

OCI DevOps integrates with OCI Logging for build and deployment logs, OCI Notifications for event-based alerting, and OCI Monitoring for pipeline metrics. Every build run and deployment run captures detailed logs that you can query and search. Failed stages include error messages, exit codes, and the specific command that failed.

bash
# View build run logs
oci devops build-run list-build-run-snapshots \
  --build-run-id <build-run-ocid>

# Get deployment run details including stage status
oci devops deployment get \
  --deployment-id <deployment-ocid> \
  --query 'data.{"Status": "lifecycle-state", "Stages": "deploy-pipeline-artifacts", "Progress": "deployment-execution-progress"}' \
  --output json

# List all deployment runs for a pipeline
oci devops deployment list \
  --deploy-pipeline-id <deploy-pipeline-ocid> \
  --query 'data.items[].{"ID": id, "Status": "lifecycle-state", "Created": "time-created", "Type": "deployment-type"}' \
  --output table

# View logs for a specific build stage
oci logging search \
  --search-query 'search "<log-group-ocid>" | where buildPipelineId = "<build-pipeline-ocid>" | sort by datetime desc | limit 50' \
  --time-start "2026-03-14T00:00:00Z" \
  --time-end "2026-03-14T23:59:59Z"

# Roll back a deployment
oci devops deployment create-pipeline-redeployment \
  --deploy-pipeline-id <deploy-pipeline-ocid> \
  --previous-deployment-id <previous-successful-deployment-ocid> \
  --display-name "rollback-to-v1.2.3"

Build Timeouts

The default build stage timeout is 10 minutes (600 seconds). For large projects with extensive test suites or multi-stage Docker builds, increase the timeout in the build_spec.yaml file or the stage configuration. Maximum allowed timeout is 480 minutes (8 hours). If builds consistently time out, consider splitting into parallel stages, using build caching, or selecting a larger build runner shape.

Best Practices for OCI DevOps

Effective CI/CD on OCI requires thoughtful pipeline design, security configuration, and operational practices. Here are key recommendations for production deployments.

Pipeline Design Recommendations

PracticeWhyHow
Separate build and deploy pipelinesReuse builds across environmentsOne build pipeline, multiple deploy pipelines per env
Use approval stages for productionHuman gate before prod changesAdd manual approval stage before prod deploy
Implement automatic rollbackReduce incident durationEnable rollback policy on deployment stages
Pin artifact versionsReproducible deploymentsUse immutable tags and digests
Cache build dependenciesFaster buildsUse OCI Object Storage for Maven/npm caches
Run security scansShift security leftAdd SAST/container scan stages

Security is paramount in CI/CD pipelines. Never hardcode secrets in build specs or deployment manifests. Use OCI Vault to store secrets and reference them by OCID. Use dynamic groups with least-privilege policies for pipeline resources. Enable audit logging to track all pipeline changes and deployments for compliance.

For multi-environment workflows, create separate deployment pipelines for development, staging, and production, each targeting different OKE clusters or instance groups. Use the same build artifacts across all environments to ensure consistency. Parameterize environment-specific values (database URLs, API keys) using pipeline parameters rather than rebuilding for each environment.

Getting Started with Oracle CloudTerraform on OCIOCI Security Best Practices

Key Takeaways

  1. 1OCI DevOps provides integrated build and deployment pipelines with native OCI IAM integration.
  2. 2Build specifications (build_spec.yaml) define build steps, environment variables, and output artifacts.
  3. 3Deployment pipelines support rolling, blue-green, and canary strategies for OKE and compute targets.
  4. 4Build triggers automatically start pipelines on code push, pull request, or tag creation events.

Frequently Asked Questions

Does OCI DevOps charge for the CI/CD service?
OCI DevOps has no additional service charges. You pay only for the compute used by build runners and deployment targets. Build pipelines use managed runners with shapes you select, billed per minute of compute usage. The OCI Code Repository (managed Git) is free with no storage limits.
Can I use GitHub or GitLab with OCI DevOps?
Yes. OCI DevOps supports external connections to GitHub, GitLab, and Bitbucket Cloud. Store your personal access token in OCI Vault and reference it in the connection. Build pipelines can trigger on push events from external repositories through webhook integration, or you can mirror external repos to OCI Code Repository.

Written by CloudToolStack Team

Cloud engineers and architects with hands-on experience across AWS, Azure, and GCP. We write guides based on real-world production patterns, not just documentation rewrites.

Disclaimer: This guide is for educational purposes. Cloud services change frequently; always refer to official documentation for the latest information. AWS, Azure, and GCP are trademarks of their respective owners.