feat(jira): add flyteplugins-jira - #1517
Merged
Merged
Conversation
This was referenced Sep 1, 2026
cosmicBboy
force-pushed
the
nielsb/webhooks-clickup
branch
from
September 1, 2026 17:36
410aa4a to
d1b3007
Compare
cosmicBboy
force-pushed
the
nielsb/webhooks-jira
branch
from
September 1, 2026 17:36
b80b854 to
12f52a8
Compare
cosmicBboy
marked this pull request as ready for review
September 1, 2026 17:54
cosmicBboy
force-pushed
the
nielsb/webhooks-clickup
branch
from
September 1, 2026 18:29
d1b3007 to
69f870c
Compare
cosmicBboy
force-pushed
the
nielsb/webhooks-jira
branch
from
September 1, 2026 18:29
12f52a8 to
810887e
Compare
cosmicBboy
force-pushed
the
nielsb/webhooks-clickup
branch
from
September 1, 2026 18:54
69f870c to
7e85ea9
Compare
cosmicBboy
force-pushed
the
nielsb/webhooks-jira
branch
from
September 1, 2026 18:54
810887e to
ad263c9
Compare
cosmicBboy
force-pushed
the
nielsb/webhooks-clickup
branch
from
September 2, 2026 00:56
7e85ea9 to
8e7e70f
Compare
cosmicBboy
force-pushed
the
nielsb/webhooks-jira
branch
from
September 2, 2026 00:56
ad263c9 to
c64d70f
Compare
cosmicBboy
force-pushed
the
nielsb/webhooks-clickup
branch
from
September 2, 2026 01:03
8e7e70f to
3ad4f51
Compare
cosmicBboy
force-pushed
the
nielsb/webhooks-jira
branch
from
September 2, 2026 01:03
c64d70f to
c43099a
Compare
Receive Jira webhooks in Flyte. Exports JiraProvider, a Provider subclass with its
defaults pre-wired, so wiring it up reads:
WebhookAppEnvironment(providers=[JiraProvider()])
The receiver itself ships with flyte, at flyte.extras.webhooks; this package
contributes only what is specific to Jira -- which environment variable holds
the secret, how to verify a delivery, how to parse one into a WebhookEvent, and
typed constants for every event Jira sends.
examples/jira_webhooks.py runs with no Jira account at all: --local replays
this plugin's own SAMPLE_DELIVERY through the app. The shared conformance check
exercises that same sample.
The package is named for the product rather than for webhooks, so client
methods can land here later when they earn their place -- as review_pr does in
flyteplugins-github, where flyte.new_condition is the part no vendor SDK can
provide. Plain API passthrough belongs in the vendor's own SDK.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VKZrTNjjWVzTZUxDFbn4Nk
Signed-off-by: Niels Bantilan <niels.bantilan@gmail.com>
cosmicBboy
force-pushed
the
nielsb/webhooks-clickup
branch
from
September 2, 2026 01:32
3ad4f51 to
42db125
Compare
cosmicBboy
force-pushed
the
nielsb/webhooks-jira
branch
from
September 2, 2026 01:32
c43099a to
b572d16
Compare
…1518) Last of the webhook plugin stack (#1512–#1517), based on #1517 so every import resolves. Worked recipes for driving GitHub, Slack, Linear, ClickUp, and Jira from Flyte, plus one app receiving webhooks from all five. ## The argument these examples make There is deliberately **no Flyte client plugin** for these products. Each vendor already ships (or the community maintains) a Python client tested against the live API by people who get deprecation notices first, and a task is just a function — so calling `PyGithub` or `slack_sdk` from a task needs nothing in between. A wrapper would only add a surface to keep in sync with someone else's release calendar. What Flyte contributes, and what these use: - `flyteplugins-webhooks-*` — authenticate an inbound delivery and normalize it - `idempotent_run` — launch a run once per event key - `flyte.new_condition` — park a run on a human decision with a typed payload back | File | Shows | Client | | --- | --- | --- | | `webhook_receiver.py` | One app receiving from all five products | `flyteplugins-webhooks-*` | | `github_pr_review_gate.py` | Human-gated merge: a condition carrying JSON, parsed into a typed decision | `PyGithub` | | `github_triage_pr.py` | Label, comment, report a check run | `PyGithub` | | `slack_notify.py` | Post, thread, react, answer a mention | `slack_sdk` | | `linear_triage_issue.py` | Query a backlog and comment, over GraphQL | `gql` | | `clickup_manage_ticket.py` | Open and close tickets, with a status pre-check | `httpx` | | `jira_manage_ticket.py` | Open, transition, and search issues | `jira` | Linear and ClickUp ship no official Python SDK — Linear's API is a single GraphQL endpoint so `gql` is the maintained client, and ClickUp's is a handful of REST calls where `httpx` directly beats a thin third-party wrapper. The review gate is here rather than in a plugin because `flyte.new_condition` is the only part of it that needed inventing; the rest is PyGithub calls. ## One thing I fixed while writing them Task names are **environment-qualified** — `triage_pr` in `github_triage_pr.py` deploys as `github-triage.triage_pr`, which is what the receiver looks up. Bare names never resolve, and both the Linear and Jira recipes define a `triage_issue`, so the qualifier is also what keeps them apart. There is a check that every name the receiver launches is actually defined; the original per-product examples this replaces had bare names throughout and would have failed at the first real event. ## Verification Verified mechanically rather than by eye: every referenced example path resolves, every `flyte create secret` name matches the actual provider `secret_env`, every `flyte deploy <file> <env>` names a real `TaskEnvironment`, every `flyte run` task is defined, and every example file executes (the receiver registers all five handlers). `make fmt`, `make mypy`, `make ty`, ruff, and codespell pass. Signed-off-by: Niels Bantilan <niels.bantilan@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of the webhook plugin stack. Requires #1512 (
flyteplugins-webhooks-core), which is this PR's base — the diff here is just this package.Receive Jira webhooks in Flyte.
What it implements
The
Providercontract from core: which environment variable holds the secret, how to verify a delivery, how to parse one into aWebhookEvent, plus typed constants for every event Jira sends.Verification: none — Jira Cloud does not sign its webhooks.
Because there is no signature, this plugin authenticates with a shared token in
X-Webhook-Token, which something in front of the app has to inject since Jira cannot send custom headers.PROVIDER.signedis False, so the dashboard says the product does not sign rather than implying a guarantee that is absent.This is the plugin that made the conformance harness better: it caught that a shared token, unlike an HMAC, is not bound to the request body, so a tampered payload still verifies. That is inherent to an unsigned webhook rather than a bug here, and
signed=Falsenow opts out of that one check explicitly instead of the harness quietly passing.Conformance
Runs the shared
assert_provider_conforms, which replays this plugin'sSAMPLE_DELIVERY— a real Jira payload — throughverifyandparserather than trusting them to agree with each other. It also asserts the verifier returns False rather than raising on a hostile header, that event constants render as wire values rather than enum names, and that the sample parses to something the constants actually spell.6 tests.
make fmt,make mypy,make ty, ruff, and codespell pass.What it does not do
Call the Jira API. Use the
jirapackage directly from your tasks — the recipes are in the examples PR at the end of this stack. This plugin owns only the part that is Flyte's: authenticating an inbound delivery and turning it into a run.