Alright, let's talk about the part everyone conveniently forgets until the migration is halfway done and burning: triggers that aren't just "git push."
You're migrating from, say, Jenkins or GitLab CI to something like GitHub Actions or ArgoCD. You've mapped the jobs, you're sweating over the secrets migration, and then you remember: "Oh right, half our pipelines are kicked off by a Slack message, a cron schedule on the third Tuesday of the month, or a webhook from some internal artifact registry that hasn't been updated since 2019."
The sales pitch for the new platform always highlights "GitOps!" but is conspicuously quiet about everything else. So, how do you actually move these?
**The usual suspects you'll need to audit:**
* Scheduled (cron) jobs: Easy on paper, but timezone and schedule syntax differences will bite you.
* External webhooks (Jira, Artifactory, custom apps): This is where the pain lives. The old system had a URL; the new one needs a new one. That means updating the *sender*, which involves tickets, other teams, and hope.
* Manual triggers from UI/API: You'll need to replicate the parameters and permissions. Did the old system let project managers trigger a deploy? Hope your new RBAC model can do that (and *should* it?).
* Pipeline-chaining: One pipeline triggering another, often across project boundaries. Turns into a distributed tracing problem real fast.
**A concrete example from my last audit:**
Jenkins had a job triggered by a generic webhook from a monitoring alert. The migration plan said "re-implement in GitHub Actions." The team built the new workflow... and stalled for weeks because updating the webhook sender required a change request to the *monitoring team's* deployment, which was on a quarterly release cycle. The "two-week migration" took three months.
```yaml
# GitHub Actions example for a schedule AND a repository_dispatch (manual API trigger)
name: Deploy on Schedule or Manual
on:
schedule:
- cron: '30 2 * * 1-5' # 2:30 AM UTC every weekday
repository_dispatch:
types: [deploy-prod]
```
You see the gap? The `repository_dispatch` needs a token and an API call. What *was* a simple button click in a UI now requires docs and a script. The cron is easy, but was it supposed to be in UTC or PST? Who knows.
**The real questions you should be asking:**
* Have you done a full inventory of *all* triggers, not just the ones in your main `.gitlab-ci.yml` or `Jenkinsfile`? Check the legacy folders.
* For each external dependency, who owns the sender system, and what's their change process?
* Are you using this migration as an excuse to deprecate truly bizarre, untraceable triggers? (You should.)
* How will you audit trigger failures in the new system? It's usually worse.
I want the gritty details. What was the actual blocker? Was it legal/compliance sign-off on the new webhook endpoint? Was it that the new system charges per minute and your cron job now costs more than the service it runs?
- Nina
- Nina
Yeah, cron syntax differences got me too when I moved from Jenkins to GitHub Actions. The "third Tuesday" thing? I had to write a weird custom cron expression that felt wrong. Ended up using a scheduled workflow with a matrix to check the day-of-week. 😅
But the webhooks are the real blocker, right? It's not just making a new endpoint; it's the coordination hell. Did you find a good way to stage the cutover for those, or do you just have to accept some pipeline downtime?
Containers are magic, but I want to know how the magic works.
The cron syntax differences are trivial next to the real coordination problem you mentioned. Everyone focuses on replicating the trigger mechanism but forgets the payload.
Vendors will tell you to just point the webhook at the new endpoint. What they don't mention is that the old system expected a payload with `{ "artifact": "foo-v1.2.3" }` and the new one throws an error because it demands `{ "release_tag": "v1.2.3-foo" }`. And the team that owns the registry sending the hook? Good luck getting their roadmap updated.
So no, you can't just accept downtime. You need a dual-listener setup during the transition, and even then, you're debugging why the new system ignored a payload the old one happily consumed. The sales material never includes a timeline for rewriting your internal services' notification formats.
— skeptical but fair
Scheduled workflows with a day-of-week matrix is exactly the right hack for those non-standard cron needs. It's ugly, but it gets the job done when the new system's scheduler is less flexible.
As for the webhook coordination hell, you can't just accept downtime. You have to run both systems in parallel for a while, fed from the same source. The trick is to put a small proxy or fan-out in front - something that listens once and forwards the payload to both the old and new pipeline endpoints. That way you can compare execution and debug payload mismatches without dropping events. It's extra scaffolding you'll tear down later, but it's the only way to migrate without causing a panic.
Speed up your build
Fan-out proxy is fine in theory. Who's gonna maintain it? That's more infrastructure that can break.
And good luck when your new system's retry logic doesn't match the old one. Proxy forwards, new system chokes on a malformed date, and you're left wondering which logs to check.
-- old school