What this prompt does
This prompt generates a full, stage-by-stage CI/CD pipeline tailored to your specific platform, project type, and toolchain. By parameterizing every meaningful decision — lint tool, test framework, coverage threshold, security scanner, artifact target, staging environment, production environment, and notification channel — the template produces pipeline config that slots directly into your workflow rather than requiring heavy post-generation editing.
What makes it work is the logical sequencing baked into the structure: linting and style checks run first (cheapest failures), then tests with a hard coverage gate, then security scanning before any build artifact is produced. Staging deploys are automatic on develop merges; production requires manual approval. That approval gate is explicit in the prompt, so the output actually includes it rather than leaving it as a comment placeholder.
The prompt also explicitly asks for caching strategy, parallel job configuration, rollback procedures, and failure notifications — details that most engineers forget to specify and then spend hours retrofitting.
When to use it
- Setting up CI/CD from scratch on a new Laravel, Node, or Python project and want a production-ready baseline in one pass.
- Migrating from one platform to another (e.g., Jenkins to GitHub Actions) and need a complete rewrite rather than a patch.
- Adding a security scanning stage (SAST, dependency audit) to an existing pipeline that only runs tests.
- Onboarding a client project where you need to document and enforce a coverage gate immediately.
- Building a staging-gated workflow where QA sign-off happens before production and rollback must be explicit.
- Creating a pipeline template to standardize across multiple microservices in a monorepo.
Example output
For [ci_platform]=GitHub Actions, [project_type]=Laravel, [lint_tools]=PHP CS Fixer + PHPStan, [test_framework]=PHPUnit, [coverage_target]=80, [security_scan]=Trivy, [build_artifacts]=Docker image, [staging_env]=Hetzner staging, [prod_env]=Hostinger VPS, [notification_channel]=Slack #deployments:
name: Laravel CI/CD
on:
push:
branches: [develop, main]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/cache@v4
with:
path: vendor
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- run: composer install --no-interaction
- run: vendor/bin/pint --test
- run: vendor/bin/phpstan analyse --level=8
test:
needs: lint
runs-on: ubuntu-latest
env:
XDEBUG_MODE: coverage
steps:
- uses: actions/checkout@v4
- uses: actions/cache@v4
with:
path: vendor
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- run: composer install --no-interaction
- run: php artisan test --coverage --min=80
security:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: aquasecurity/[email protected]
with:
scan-type: fs
exit-code: 1
build:
needs: security
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- run: docker build -t mejba/app:${{ github.sha }} .
- run: docker push mejba/app:${{ github.sha }}
deploy-staging:
needs: build
if: github.ref == 'refs/heads/develop'
runs-on: ubuntu-latest
steps:
- name: Deploy to staging
env:
SSH_KEY: ${{ secrets.STAGING_SSH_KEY }}
run: |
echo "$SSH_KEY" > /tmp/deploy_key && chmod 600 /tmp/deploy_key
ssh -i /tmp/deploy_key -o StrictHostKeyChecking=no deploy@staging \
"docker pull mejba/app:${{ github.sha }} && docker-compose up -d"
deploy-production:
needs: build
if: github.ref == 'refs/heads/main'
environment:
name: production
url: https://mejba.me
runs-on: ubuntu-latest
steps:
- name: Record last stable image
id: last_stable
run: echo "tag=$(ssh -i /tmp/deploy_key deploy@hostinger 'docker ps --format \"{{.Image}}\" | head -1 | cut -d: -f2')" >> $GITHUB_OUTPUT
- name: Deploy to production
env:
SSH_KEY: ${{ secrets.PROD_SSH_KEY }}
run: |
echo "$SSH_KEY" > /tmp/deploy_key && chmod 600 /tmp/deploy_key
ssh -i /tmp/deploy_key -o StrictHostKeyChecking=no deploy@hostinger \
"docker pull mejba/app:${{ github.sha }} && docker-compose up -d"
- name: Rollback on failure
if: failure()
env:
SSH_KEY: ${{ secrets.PROD_SSH_KEY }}
LAST_STABLE: ${{ steps.last_stable.outputs.tag }}
run: |
echo "$SSH_KEY" > /tmp/deploy_key && chmod 600 /tmp/deploy_key
ssh -i /tmp/deploy_key -o StrictHostKeyChecking=no deploy@hostinger \
"docker-compose down && docker run -d mejba/app:$LAST_STABLE"
- name: Notify Slack on failure
if: failure()
uses: slackapi/[email protected]
with:
payload: '{"text":"Production deploy failed for ${{ github.sha }} — rollback triggered."}'
env:
SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK }}
Pro tips
- Set
[coverage_target]to your current baseline, not your aspiration. If the project sits at 42% today, gating at 80% blocks every branch on day one. Commit--min=42, get the gate enforced, then open a dedicated ticket to ratchet it up 5 points per sprint. The prompt will generate the incremental version too if you ask it separately. - Pin
[security_scan]action versions explicitly. The generated output pins to a specific tag (e.g.,[email protected]) rather than@master. Floating refs in security jobs are a supply-chain risk — someone else controls what runs in your pipeline. If you ask for Semgrep or Snyk instead, verify the generated version tag before merging. - Use
[notification_channel]=PagerDutyfor production pipelines, not Slack. The output will generate on-call alert payloads with severity and dedup keys rather than chat messages. Slack is fine for staging failures; production rollbacks warrant a different escalation path and a different integration endpoint. - The rollback step requires capturing the running image tag before the deploy step runs. The example shows this with a
last_stableoutput step — if you omit that capture pattern, the rollback has nothing to revert to. Review the generated rollback logic carefully; it is the one step most likely to need manual tuning for your actual container runtime. - For monorepos, set
[project_type]to something likeLaravel + React monorepoand[build_artifacts]toDocker image + Vite bundle. The output will generatepaths:filters on theon.pushtrigger to run jobs only when relevant directories change. Review those filters against your actual directory structure — generated path patterns are often one level off from real layouts.