Skip to main content

GitHub Actions Integration

Add DriftWise to any GitHub Actions workflow that runs terraform plan.

Workflow Example

The analyze endpoint enqueues the job and returns 202 immediately — poll GET /llm-jobs/{job_id} until status is done (or error):

.github/workflows/terraform.yml
- name: Terraform Plan
id: plan
run: terraform plan -out=tfplan

- name: DriftWise Analysis
run: |
terraform show -json tfplan > plan.json
JOB_ID=$(curl -sfX POST "https://api.driftwise.ai/api/v2/orgs/${{ vars.DRIFTWISE_ORG_ID }}/analyze" \
-H "x-api-key: ${{ secrets.DRIFTWISE_API_KEY }}" \
-H "Content-Type: application/json" \
-d "{
\"plan_json\": $(cat plan.json | jq -Rs .),
\"ci\": {
\"repo_owner\": \"${{ github.repository_owner }}\",
\"repo_name\": \"${{ github.event.repository.name }}\",
\"pr_number\": ${{ github.event.pull_request.number }},
\"commit_sha\": \"${{ github.sha }}\",
\"branch\": \"${{ github.head_ref }}\"
}
}" | jq -r '.job_id')

for i in $(seq 1 36); do
BODY=$(curl -sf "https://api.driftwise.ai/api/v2/orgs/${{ vars.DRIFTWISE_ORG_ID }}/llm-jobs/$JOB_ID" \
-H "x-api-key: ${{ secrets.DRIFTWISE_API_KEY }}")
STATUS=$(echo "$BODY" | jq -r '.status')
if [ "$STATUS" = "done" ]; then RESULT=$(echo "$BODY" | jq '.result'); break; fi
if [ "$STATUS" = "error" ]; then echo "analysis failed: $(echo "$BODY" | jq -r '.error')" >&2; exit 1; fi
sleep 5
done
[ "$STATUS" = "done" ] || { echo "timed out waiting for analysis" >&2; exit 1; }

echo "$RESULT" | jq -r '.narrative'

Secrets & Variables

Add these in your repository settings (Settings > Secrets and variables > Actions):

TypeNameValue
SecretDRIFTWISE_API_KEYYour API key (dw2_...)
VariableDRIFTWISE_ORG_IDYour organization ID

Response

analyze only returns job_id, scan_run_id, and status: "pending" — poll llm-jobs/{job_id} for the actual analysis, then parse result with jq to post a PR comment or set step outputs:

- name: DriftWise Analysis
id: driftwise
run: |
terraform show -json tfplan > plan.json
JOB_ID=$(curl -sfX POST "https://api.driftwise.ai/api/v2/orgs/${{ vars.DRIFTWISE_ORG_ID }}/analyze" \
-H "x-api-key: ${{ secrets.DRIFTWISE_API_KEY }}" \
-H "Content-Type: application/json" \
-d "{\"plan_json\": $(cat plan.json | jq -Rs .)}" | jq -r '.job_id')

for i in $(seq 1 36); do
BODY=$(curl -sf "https://api.driftwise.ai/api/v2/orgs/${{ vars.DRIFTWISE_ORG_ID }}/llm-jobs/$JOB_ID" \
-H "x-api-key: ${{ secrets.DRIFTWISE_API_KEY }}")
STATUS=$(echo "$BODY" | jq -r '.status')
if [ "$STATUS" = "done" ]; then RESULT=$(echo "$BODY" | jq '.result'); break; fi
if [ "$STATUS" = "error" ]; then echo "analysis failed: $(echo "$BODY" | jq -r '.error')" >&2; exit 1; fi
sleep 5
done
[ "$STATUS" = "done" ] || { echo "timed out waiting for analysis" >&2; exit 1; }

echo "risk_level=$(echo "$RESULT" | jq -r '.risk_level')" >> $GITHUB_OUTPUT
echo "$RESULT" | jq -r '.narrative'