Automating pipeline execution through various triggers: manual, cron schedules with the hash symbol, SCM polling, GitHub and GitLab webhooks, and Multibranch Pipelines for per-branch and per-pull-request automation.

In episode 3 we built the machine: a healthy controller, agents ready to work, and labels to direct jobs. But a machine is only useful if something turns it on. The question in episode 4 is: what triggers a pipeline to run? The answer is triggers — and choosing the right trigger determines how quickly a code change reaches production.
In the real world, this is the difference between teams whose builds run "when they remember" and teams where every push automatically triggers the pipeline. This episode covers manual triggers (UI/CLI), cron schedules with the hash symbol, SCM polling, webhooks from GitHub and GitLab, payload parsing with the Generic Webhook Trigger, and Multibranch Pipelines and Organization Folders for per-branch and per-pull-request automation.
The simplest way is pressing the Build Now button on the job page. This is useful for testing and admin jobs. But in automation, manual triggering is done via the CLI — for example triggering a build from the terminal or from an external tool:
curl -u admin:API_TOKEN -X POST "http://localhost:8080/job/my-app/build"
curl -u admin:API_TOKEN -X POST "http://localhost:8080/job/my-app/buildWithParameters"To trigger a build programmatically, you need an API token (created in your user profile) and, if CSRF protection is active, a crumb — Jenkins rejects POSTs without a crumb coming from outside the UI. This is a built-in security mechanism that should never be turned off. If you just want to test, curl can be used directly from the terminal.
Jenkins can schedule builds like Linux cron, but with one important difference: a five-field format (minute, hour, day-of-month, month, day-of-week) and support for the hash symbol H.
pipeline {
agent any
triggers {
cron('H 2 * * *')
}
stages {
stage('Build') {
steps {
echo 'Build terjadwal berjalan'
}
}
}
}cron('H 2 * * *') means once a day, between 2:00 and 2:59. The H (hash) symbol makes Jenkins choose a minute deterministically yet spread out — important when many jobs share the same schedule, for example when all backup pipelines are scheduled H 2 * * *. Without the hash, all jobs would stampede at the exact same minute — a phenomenon called the thundering herd. With the hash, the chosen minutes are spread automatically and the load is distributed.
| Syntax | Meaning |
|---|---|
H * * * * | Once every hour, at a fixed random minute |
H/15 * * * * | Every 15 minutes, starting from a hash point |
H 9-17/2 * * 1-5 | Every 2 hours between 9-17, on workdays |
@daily | Once a day (same as H H * * *) |
If you cannot (or do not yet want to) set up a webhook, SCM polling is the middle ground: Jenkins checks the repository periodically and only runs a build if there are changes.
pipeline {
agent any
triggers {
pollSCM('H/15 * * * *')
}
stages {
stage('Build') {
steps {
echo 'Di-poll dan ada perubahan, build dijalankan'
}
}
}
}Polling performs a fetch to the repository at every interval — no changes, no build; with changes, a build runs with the latest commit. This is more economical than a scheduled build that runs blindly, but it is still slower than a webhook and adds load to the Git server. The rule of thumb: webhooks for responsive automation, pollSCM as a fallback, cron for recurring work that does not depend on commits.
The webhook is the most precise way: the Git server sends a notification to Jenkins every time there is an event — a push, a pull request, or a tag. Jenkins does not need to wait or guess.
The basic steps:
http://<jenkins>/github-webhook/ (GitLab: /project/<id>), and select the events you want (push, pull request).When a push lands on GitHub, GitHub contacts Jenkins, Jenkins verifies the event, and the relevant pipeline runs immediately. No polling, no delay — changes on the main branch can reach staging within seconds.
Not every SCM system has an official plugin. For Bitbucket, Gitea, or your own internal tools, use the Generic Webhook Trigger plugin. It accepts any HTTP POST and then extracts values from the JSON payload using JSONPath:
triggers {
GenericTrigger(
token: 'deploy-webhook',
genericVariables: [
[key: 'REF', value: '$.ref'],
[key: 'BRANCH', value: '$.repository.branch']
],
printContributedVariables: true,
printPostContent: true
)
}The token here acts as a secret key: the trigger URL becomes http://localhost:8080/generic-webhook-trigger/invoke?token=deploy-webhook. The incoming JSON payload is parsed, and the ref value and branch name are extracted into pipeline variables that can be used in later stages. This is the most flexible tool because it does not depend on a specific SCM event format.
Warning
Webhooks open a door into Jenkins from the outside. Make sure Jenkins cannot be accessed anonymously, use a long and secret token for the Generic Webhook Trigger, and always verify that Jenkins only accepts events from legitimate sources.
Per-branch triggers are usually still manual: for each branch, a job has to be created separately. Multibranch Pipelines eliminate that work — one job scans the repository and automatically creates a sub-job for every branch, tag, and pull request it finds, as long as that branch has a Jenkinsfile.
The benefits are immediately felt:
On top of that there is the Organization Folder (for GitHub/GitLab/Bitbucket): a single folder that scans the entire organization and creates a Multibranch Pipeline for every repository that contains a Jenkinsfile. You can get CI for dozens of repos with just one configuration entity.
| Feature | Freestyle + Webhook | Multibranch Pipeline | Organization Folder |
|---|---|---|---|
| Scope | One job, one branch | One repo, all branches/PRs | All repos in the organization |
| Per-branch pipeline | Manual | Automatic | Automatic |
| Setup per repo | Yes | Yes | Once for the whole org |
| Best for | Simple jobs | Active projects | Enterprise scale |
In episode 4 you have understood:
cron('H H * * *'), including the meaning of the hash symbol to prevent the thundering herd.pollSCM('H/15 * * * *') as a fallback when webhooks are unavailable.The key takeaway to carry with you: choose the trigger that matches the nature of the work — webhooks for responsiveness, cron for fixed schedules, SCM polling as a backup, and Multibranch for per-branch automation. In episode 5 we will dive into the "contents" of the pipeline: variables, environments, and secret management — how pipelines read the build number, job name, and commit, and how to store and retrieve secrets safely using Credentials and withCredentials. See you in episode 5!