Understanding CI/CD Triggers
What Is a Trigger in Simple Terms
A trigger is the alarm clock for your pipeline. Without a trigger, a pipeline sits idle forever — knowing what to run but waiting for a reason to run it. The trigger says: now is the time, this is the context, start the pipeline.
Different events should start different pipelines. A commit to a feature branch should run tests only. A merge to main should run tests, scan, and deploy to staging. A Git tag like v1.2.3 should deploy to production. Getting triggers right means the right automation runs at the right time.
How It Works
+------------------------------------------+| Trigger Types || || push: git push to branch || -> run CI on the new commit || || pull_request: PR opened or updated || -> run tests, post status || || tag: git tag v1.2.3 pushed || -> deploy to production || || schedule: cron expression || -> nightly security scans || || workflow_dispatch: manual button click || -> run with custom inputs |+------------------------------------------+Complete trigger configuration (GitHub Actions):
on: ## Trigger on push to main and release branches push: branches: - main - 'release/**' ## Only trigger if these paths changed paths: - 'src/**' - 'Dockerfile' - '.github/workflows/**' ## Trigger on pull requests to main pull_request: branches: - main types: [opened, synchronize, reopened] ## Trigger on version tags push: tags: - 'v*.*.*' ## Nightly security scan at 2 AM IST (8:30 PM UTC) schedule: - cron: '30 20 * * *' ## Manual trigger with inputs workflow_dispatch: inputs: environment: description: 'Target environment' required: true default: 'staging' type: choice options: [staging, production] skip_tests: description: 'Skip tests (emergency only)' type: boolean default: falseGitLab CI trigger rules:
deploy-production: stage: deploy script: - ./deploy.sh production ## Only run on main branch tags, never on MRs rules: - if: $CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/ when: manual - when: neverPractical Commands
## GitHub Actions -- trigger workflow manuallygh workflow run deploy.yaml \ --field environment=staging \ --field skip_tests=false ## GitHub Actions -- trigger via APIcurl -X POST \ -H "Authorization: Bearer $GITHUB_TOKEN" \ https://api.github.com/repos/OWNER/REPO/actions/workflows/deploy.yaml/dispatches \ -d '{"ref":"main","inputs":{"environment":"staging"}}' ## Create a Git tag to trigger production deploygit tag -a v1.2.3 -m "Release v1.2.3"git push origin v1.2.3Troubleshooting
| Symptom | Check | What to Look For |
|---|---|---|
| Pipeline not triggering on push | Branch name filter | Exact branch name match |
| Trigger loop (pipeline triggers itself) | Workflow permissions | Use github.actor != 'github-actions' guard |
| Schedule not running | Cron syntax | Validate at crontab.guru |
PLACEMENT PRO TIP**Tip:** Use path filters on push triggers to avoid running the full pipeline when only documentation changes. `paths: ['src/**', 'Dockerfile']` skips the pipeline when someone only edits a README — saving runner minutes and engineer attention.
COMMON MISTAKE / WARNING**Security:** Be careful with pull_request_target trigger in GitHub Actions. It runs in the context of the base repository (has access to secrets) even for forks. An attacker can craft a malicious fork PR that exfiltrates secrets. Use pull_request (no secret access) for untrusted contributions and pull_request_target only when secret access is explicitly needed and the code is audited first.
COMMON MISTAKE / WARNING**Common Mistake:** Triggering the full production deployment pipeline on every push to main instead of every merge. If your main branch allows direct pushes, each push triggers a deployment. This leads to many small deploys that are hard to track. Use branch protection rules to require PRs to main, so deployments only happen on deliberate merges.
REMEMBER THIS**Remember:** Scheduled triggers only fire if the repository has had activity in the last 60 days on GitHub Actions. Inactive repositories have their scheduled workflows disabled automatically. If your nightly security scan stops running, check whether the repository was dormant and re-enable the schedule.