AI-Assisted DevOps Workflows¶
Put the four AI assistants in the images (Claude Code, Codex CLI, Copilot CLI and Antigravity CLI) to work on real infrastructure tasks: reviewing changes, writing modules, explaining failures and reviewing pull requests in CI.
Sign in first
Every example assumes you've signed in, or are passing a CI token. See the AI CLI setup guide for each assistant's login, environment variables and config directory. Google's Gemini CLI has been replaced by Antigravity CLI (agy), and the examples use agy.
The golden rule: AI suggests, tools verify¶
AI output is a first draft. Every workflow here runs the image's deterministic tools on it before anything reaches a cloud account.
flowchart LR
A["AI review or<br/>generate"] --> V["terraform validate<br/>tflint ยท ansible-lint"]
V --> S["trivy config"]
S --> P["terraform plan"]
P --> H{"Human<br/>review"}
H -->|approve| D["terraform apply"]
H -->|changes| A
classDef ai fill:#d97706,stroke:#b45309,color:#fff
classDef base fill:#0891b2,stroke:#0e7490,color:#fff
classDef neutral fill:#334155,stroke:#1e293b,color:#fff
classDef all fill:#059669,stroke:#047857,color:#fff
class A ai
class V,S,P base
class H neutral
class D all
All the snippets below run inside the container, from a shell started like this (mount only the logins you use):
docker run -it --rm \
-v "$PWD":/srv -w /srv \
-v ~/.claude:/root/.claude \
-v ~/.claude.json:/root/.claude.json \
-v ~/.codex:/root/.codex \
-v ~/.copilot:/root/.copilot \
-v ~/.gemini:/root/.gemini \
-v ~/.aws:/root/.aws \
ghcr.io/jinalshah/devops/images/all-devops:latest
Feeding files to an assistant
None of the CLIs has a --file flag. Either pipe content in (git diff | claude -p "..."), or name the files in the prompt, since each agent can read the working directory itself.
Workflow 1: Review changes before you apply¶
The same review, done with whichever assistant you have. Piping git diff keeps the model focused on what changed.
Then let the deterministic tools have their say:
Workflow 2: Generate a module, then prove it¶
Let an agent write files directly rather than redirecting its chat output into a .tf file. You get clean HCL across several files.
Prove it before trusting it:
cd modules/vpc
terraform init -backend=false
terraform fmt -check && terraform validate && tflint
trivy config .
Second opinion
Generate with one assistant and review with another, for example codex exec to write and git diff | claude -p "review" to check. Different models tend to catch different mistakes.
Workflow 3: Explain a failure¶
Pipe the error straight in. 2>&1 makes sure stderr, where most tools write their errors, comes along too.
terraform apply 2>&1 | tee apply.log
claude -p "This terraform apply failed. Explain the root cause, give a step-by-step fix,
and say how to prevent it. The config is in the current directory." < apply.log
It works the same for Kubernetes and Ansible:
kubectl describe pod my-app-7d9c -n prod | agy -p "Why is this pod not starting?"
ansible-playbook site.yml 2>&1 | tail -50 | codex exec "Explain this Ansible failure and suggest a fix"
Workflow 4: Triage security scan results¶
Scanners are thorough but noisy. Let an assistant sort the findings and draft the fixes:
trivy config --format json . > trivy.json
agy -p "Summarise trivy.json for an engineer: group findings by severity,
list the top five to fix first, and show the Terraform change for each." > trivy-triage.md
Workflow 5: Keep module docs up to date¶
for module in modules/*/; do
echo "Documenting $module"
claude --permission-mode acceptEdits -p "Write ${module}README.md for the Terraform module in ${module}:
purpose, a table of inputs (type, default, description), a table of outputs,
and a usage example. Base it only on the .tf files in that directory."
done
CI: AI review on every pull request¶
The images already contain git, gh and all four assistants, so a review job just needs a token.
name: AI review
on:
pull_request:
paths: ['terraform/**', 'ansible/**']
permissions:
contents: read
pull-requests: write
jobs:
ai-review:
runs-on: ubuntu-latest
container:
image: ghcr.io/jinalshah/devops/images/all-devops:latest
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- name: Review the diff
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
git diff "origin/${{ github.base_ref }}...HEAD" -- terraform ansible \
| claude -p "Review this pull request diff for security issues, bugs and
risky infrastructure changes. Be specific and concise; use Markdown." \
> review.md
- name: Comment on the PR
env:
GH_TOKEN: ${{ github.token }}
run: gh pr comment ${{ github.event.pull_request.number }} --repo "$GITHUB_REPOSITORY" --body-file review.md
- name: Review the diff
env:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_PAT }}
run: |
git config --global --add safe.directory "$GITHUB_WORKSPACE"
git diff "origin/${{ github.base_ref }}...HEAD" -- terraform > /tmp/pr.diff
copilot -s --allow-all-tools \
-p "Review the diff in /tmp/pr.diff for security issues and risky changes. Use Markdown." \
> review.md
COPILOT_PAT is a fine-grained PAT with the Copilot Requests permission. The built-in github.token can't call Copilot.
ai:review:
stage: test
image: registry.gitlab.com/jinal-shah/devops/images/all-devops:latest
variables:
GIT_DEPTH: "0"
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
script:
- >
git diff "$CI_MERGE_REQUEST_DIFF_BASE_SHA...HEAD" -- terraform
| codex exec "Review this merge request diff for security issues and risky changes. Use Markdown."
> ai-review.md
- >
curl --fail --request POST
--header "PRIVATE-TOKEN: $GITLAB_TOKEN"
--data-urlencode "body@ai-review.md"
"$CI_API_V4_URL/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes"
artifacts:
paths: [ai-review.md]
Set CODEX_API_KEY and GITLAB_TOKEN (a token with api scope) as masked CI/CD variables.
mkdir -p ~/.gemini/antigravity-cli
echo '{"modelProvider": "gemini"}' > ~/.gemini/antigravity-cli/settings.json
# GEMINI_API_KEY comes from your CI secret store
git diff origin/main...HEAD | agy -p "Review this diff for risky changes" --print-timeout 5m > review.md
If agy fails headless, it exits with code 3 and writes AGY_ERROR: {json} to stderr, so the job fails loudly.
Keep AI review advisory
Post the review as a comment and let humans decide. Don't let an AI job approve or merge, and don't give it cloud credentials it doesn't need.
Best practices¶
-
Give it evidence
Pipe in diffs, plan output, logs and scan JSON. Specific context gets specific answers.
-
Verify everything
validate,tflint,ansible-lint,trivyand a human review, every time. -
Guard secrets
Never paste credentials or
.tfstateinto a prompt. Mount only the credentials the task needs. -
Save good prompts
Keep prompts that work in scripts or
AGENTS.md/GEMINI.mdcontext files so the team reuses them.
Keeping costs down
Review the diff, not the whole repository. Pick a smaller or faster model with --model for routine checks. Set spending limits in your vendor console. Current pricing: Claude, OpenAI API, GitHub Copilot, Antigravity.
Troubleshooting¶
The command opens an interactive UI or hangs in CI
Use the non-interactive form: claude -p, codex exec, copilot -p ... --allow-all-tools or agy -p.
The input is too large
Narrow it down: git diff -- path/, tail -200 build.log, or trivy ... --severity HIGH,CRITICAL. Or skip piping, name the files in the prompt and let the agent read only what it needs.
The answers are generic
Name what to check for (IAM wildcards, 0.0.0.0/0, encryption, tags) and what shape you want back (a table, a severity ranking, a patch).
Next steps¶
- AI CLI setup guide: sign-in and flags for each assistant
- Multi-tool patterns: chain AI with Terraform, Helm and Ansible
- GitHub Actions examples: complete pipeline configurations
- Authentication guide: credential management