Skip to content

Setting Up CI/CD Using Cursor Agent

Your test suite passes locally. You push to main. Fifteen minutes later, Slack lights up: the build failed. The error message references a Node version mismatch that only exists in the CI environment. You SSH into a runner, poke around, fix the issue, push again. Now a different test fails because the database migration did not run. Two hours of your afternoon are gone — and you have not written a single line of feature code.

CI/CD pipelines are infrastructure that most developers build once and then dread touching. Cursor Agent changes this dynamic because it can generate, debug, and iterate on workflow files the same way it handles application code.

  • A complete GitHub Actions workflow generated by Cursor, with build, test, lint, and deploy stages
  • A prompt workflow for debugging CI failures without leaving your IDE
  • Cursor CLI integration for automated code review and CI fix workflows
  • Techniques for generating environment-specific deployment configs
  • A project rules setup that keeps Cursor aware of your CI/CD conventions

The fastest way to get a working pipeline is to give Cursor Agent the full context of your project’s tooling and let it generate the workflow file. The key is being specific about your runtime, package manager, and deployment target.

This prompt works because it references your actual project files. Agent reads package.json to discover your script names (maybe npm run type-check instead of npx tsc --noEmit), checks tsconfig.json for TypeScript configuration, and generates a workflow that matches your real setup — not a generic template.

After Agent generates the file, review the diff. Common issues to watch for:

  • Missing environment variables. If your tests need DATABASE_URL or API_KEY, Agent will not know unless you mention them.
  • Wrong Node version. Agent might default to Node 20 when your project uses 22. The engines field in package.json helps here.
  • Missing services. If your tests need PostgreSQL or Redis, you need to specify that in your prompt.

For projects that need a database in CI:

@.github/workflows/ci.yml @docker-compose.yml
Update the CI workflow to include a PostgreSQL 16 service container. The test step should:
1. Wait for PostgreSQL to be healthy before running tests
2. Set DATABASE_URL as an environment variable pointing to the service container
3. Run database migrations before tests using "npm run db:migrate"
4. Use the same database name and credentials as our docker-compose.yml
Keep the existing steps intact. Add the service and modify only the test step.

Once CI passes, you want automated deployment. The pattern depends on your target, but the Cursor workflow is the same: give Agent your deployment context and let it generate the configuration.

For teams that deploy to staging before production:

@.github/workflows/ci.yml @wrangler.toml
Create a multi-environment deployment pipeline:
1. CI job runs on all pushes and PRs (existing)
2. Deploy to staging: runs on push to main after CI passes
- Uses wrangler with --env staging
- Runs smoke tests against the staging URL after deploy
3. Deploy to production: manual trigger (workflow_dispatch) or tag push (v*)
- Requires staging deploy to have succeeded
- Uses wrangler with --env production
- Posts deployment notification to Slack webhook
Use GitHub environments with protection rules for production.

This is where Cursor truly shines. Instead of reading raw CI logs in a browser tab, you can paste failure output directly into Cursor and get actionable fixes.

When a build fails, copy the relevant error output from GitHub Actions. Switch to Ask mode in Cursor:

My GitHub Actions CI job failed with this error:
Error: src/lib/utils.ts(15,3): error TS2322: Type 'string | undefined'
is not assignable to type 'string'.
The failing step is "npm run type-check". This passes locally on my machine.
Here's the relevant file: @src/lib/utils.ts
Why does this fail in CI but not locally? How do I fix it?

Ask mode will analyze the file and identify the issue — often a stricter tsconfig.json in CI, a different TypeScript version, or a missing type assertion that your local editor was silently ignoring. Once you understand the problem, switch to Agent mode to implement the fix.

Cursor CLI supports a powerful pattern: automatically fixing CI failures in GitHub Actions. You can set up a workflow that triggers when your test suite fails and uses Cursor’s headless agent to analyze and fix the issue.

.github/workflows/fix-ci.yml
name: Fix CI Failures
on:
workflow_run:
workflows: [CI]
types: [completed]
permissions:
contents: write
pull-requests: write
actions: read
jobs:
attempt-fix:
if: >-
${{ github.event.workflow_run.conclusion == 'failure'
&& github.event.workflow_run.name != 'Fix CI Failures' }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Cursor CLI
run: |
curl https://cursor.com/install -fsS | bash
echo "$HOME/.cursor/bin" >> $GITHUB_PATH
- name: Configure git
run: |
git config user.name "Cursor Agent"
git config user.email "cursoragent@cursor.com"
- name: Fix CI failure
env:
CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
agent -p "Analyze the CI failure for workflow run
${{ github.event.workflow_run.id }} in repo ${{ github.repository }}.
Use gh CLI to fetch the failure logs. Identify the failing PR.
Make minimal, targeted fixes consistent with repo style.
Create a fix branch and push it. Post a comment on the PR
with a link to quick-create a PR from the fix branch." \
--force --model claude-opus-4-6 --output-format=text

This is directly supported by Cursor’s official CLI cookbook. The agent reads the failure logs, identifies the root cause, and creates a fix branch — all without human intervention. The guard condition prevents the fix workflow from triggering itself in an infinite loop.

Beyond fixing failures, you can use the Cursor CLI to review every PR automatically:

.github/workflows/code-review.yml
name: Cursor Code Review
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
review:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- name: Install Cursor CLI
run: |
curl https://cursor.com/install -fsS | bash
echo "$HOME/.cursor/bin" >> $GITHUB_PATH
- name: Review PR
env:
CURSOR_API_KEY: ${{ secrets.CURSOR_API_KEY }}
GH_TOKEN: ${{ github.token }}
run: |
agent --force --model claude-opus-4-6 --print \
"Review PR #${{ github.event.pull_request.number }}.
Get diff with gh pr diff. Flag only high-severity issues.
Max 10 inline comments. Use gh pr review --comment."

Lock down what the agent can do with a permissions file:

.cursor/cli.json
{
"permissions": {
"deny": [
"Shell(git push)",
"Shell(gh pr create)",
"Shell(gh pr merge)",
"Write(**)"
]
}
}

Create a rule file that keeps Agent aware of your CI conventions:

.cursor/rules/ci-cd.md
# CI/CD Conventions
## GitHub Actions
- All workflows live in .github/workflows/
- Use ubuntu-latest runners
- Always cache node_modules with package-lock.json hash
- Use npm ci, never npm install
- Set timeout-minutes on every job
- Use concurrency groups to cancel stale runs
## Deployment
- Staging deploys on push to main
- Production deploys on tag push (v*) with manual approval
- All deployments use Cloudflare Workers via wrangler
- Secrets are stored in GitHub Environments, not repository-level secrets
## Testing in CI
- Tests require PostgreSQL 16 service container
- DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test
- Run migrations before tests
- Generate coverage report and upload as artifact

Agent generates a workflow with YAML syntax errors. Indentation mistakes are the most common CI issue. If the workflow fails to parse, paste the error into Ask mode: “This GitHub Actions workflow has a YAML syntax error: [error]. Fix the indentation.” Agent is excellent at fixing YAML because it can see the full structure.

Caching does not work and installs are slow. Agent sometimes generates incorrect cache keys or paths. Be explicit: “Cache node_modules using actions/cache with the hash of package-lock.json as the key. The path should be node_modules, not ~/.npm.”

The deployment step runs when it should not. Conditional logic in GitHub Actions (if: expressions) is tricky. If your deploy runs on PRs when it should only run on main, paste the workflow into Ask mode: “Under what conditions does the deploy job run? I only want it on pushes to main.”

Secrets are missing in the runner. Agent cannot access your GitHub secrets configuration. When you see errors like CLOUDFLARE_API_TOKEN is not set, that is a configuration issue in your GitHub repository settings, not a code issue.

The Cursor CLI agent makes unintended changes. Always configure .cursor/cli.json with deny rules for destructive operations. Prevent git push --force, gh pr merge, and Write(**) when running the agent in CI environments.