Skip to main content

Any CI Pipeline

DriftWise is a single HTTPS endpoint. Any runner that can execute terraform show -json and POST JSON works — Jenkins, CircleCI, Buildkite, Azure Pipelines, Drone, Harness, Tekton, Argo Workflows, Bitbucket Pipelines, TeamCity, self-hosted shell scripts. No plugin, no sidecar, no agent.

The Contract

EndpointPOST https://app.driftwise.ai/api/v2/orgs/{ORG_ID}/analyze
Authx-api-key: dw2_... header
Body{"plan_json": "<terraform show -json output, as a string>", "ci": {...}}
Response{"risk_level", "narrative", "changes", "summary", "scan_run", "plan_noise"}
Timeout~120s synchronous
plan_json is a string, not a nested object

The API expects plan_json to be the raw Terraform JSON plan, encoded as a JSON string. Shell callers use jq -Rs . to turn a file into an escaped string. Language SDKs that serialize via JSON.stringify / json.dumps do this automatically — pass a string.

Step 1 — Produce a Plan JSON

Run this in any pipeline before the analysis step:

terraform plan -out=tfplan
terraform show -json tfplan > plan.json

Step 2 — Call the API

curl (any shell runner)

curl -fsSL -X POST \
"https://app.driftwise.ai/api/v2/orgs/${DRIFTWISE_ORG_ID}/analyze" \
-H "x-api-key: ${DRIFTWISE_API_KEY}" \
-H "Content-Type: application/json" \
-d "$(jq -n --rawfile plan plan.json \
--arg repo_owner "$REPO_OWNER" \
--arg repo_name "$REPO_NAME" \
--arg branch "$BRANCH" \
--arg sha "$COMMIT_SHA" \
'{plan_json: $plan, ci: {repo_owner: $repo_owner, repo_name: $repo_name, branch: $branch, commit_sha: $sha}}')"

-f makes curl exit non-zero on HTTP errors so the pipeline step fails. jq -n builds the JSON body safely (no brittle string concatenation).

CI Metadata

Every ci field is optional. Populate whatever your runner exposes — DriftWise uses it to link the analysis back to the source (PR comments, drill-down in the UI).

FieldDescription
repo_ownerOrg/user (e.g. acme-corp)
repo_nameRepository name
repo_urlFull URL to the repo
pr_numberPull/merge request number
branchSource branch
commit_shaFull commit SHA

Runner-Specific Env Var Reference

Map your runner's built-ins to the metadata fields:

Runnerrepo_ownerrepo_namebranchcommit_shapr_number
Jenkins$CHANGE_AUTHOR / parse $GIT_URLparse $GIT_URL$BRANCH_NAME$GIT_COMMIT$CHANGE_ID
CircleCI$CIRCLE_PROJECT_USERNAME$CIRCLE_PROJECT_REPONAME$CIRCLE_BRANCH$CIRCLE_SHA1parse $CIRCLE_PULL_REQUEST
Buildkite$BUILDKITE_ORGANIZATION_SLUG$BUILDKITE_PIPELINE_SLUG$BUILDKITE_BRANCH$BUILDKITE_COMMIT$BUILDKITE_PULL_REQUEST
Azure Pipelines$(Build.Repository.Name) owner$(Build.Repository.Name) name$(Build.SourceBranchName)$(Build.SourceVersion)$(System.PullRequest.PullRequestNumber)
Bitbucket Pipelines$BITBUCKET_WORKSPACE$BITBUCKET_REPO_SLUG$BITBUCKET_BRANCH$BITBUCKET_COMMIT$BITBUCKET_PR_ID
Drone$DRONE_REPO_OWNER$DRONE_REPO_NAME$DRONE_SOURCE_BRANCH$DRONE_COMMIT_SHA$DRONE_PULL_REQUEST
Tekton / Argofrom event payloadfrom event payloadfrom event payloadfrom event payloadfrom event payload

Secrets Handling

Store DRIFTWISE_API_KEY in your runner's secret store (Jenkins Credentials, CircleCI Contexts, Azure Key Vault, etc.). DRIFTWISE_ORG_ID is not sensitive — treat it like a project ID.

Failing the Pipeline on Risk

The examples above exit non-zero on high or critical. Adjust to your policy:

  • Strict: block on medium and above.
  • Advisory only: never fail, just log the narrative for reviewers.
  • Policy-driven: combine with DriftWise custom policy rules to rewrite risk on your own signals, then gate on the rewritten level.

What's Returned

The response is JSON. The fields you'll typically consume in a pipeline:

  • risk_level — one of low, medium, high, critical, unknown.
  • narrative — plain-English summary, safe to print in CI logs or post as a PR comment.
  • scan_run.id — UUID of the recorded analysis; use to deep-link back to the DriftWise UI.
  • plan_noise — counts of known-benign patterns vs. novel changes; useful for filtering noisy reviews.

Limits

  • Request body: 5 MB. Large monorepo plans may need to be split per workspace.
  • Response timeout: 120s. LLM generation dominates — slower models take longer.
  • Rate limits: depend on plan. Free tier: 10 analyses/month; Team/Enterprise: unlimited.