Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Jira Bundle Laravel Package

stingus/jira-bundle

A PHP bundle for Jira integration that provides configuration and service bindings to connect your application to Jira issues, projects, and workflows. It simplifies Jira API access and dependency injection, reducing setup boilerplate so teams can add Jira connectivity faster.

View on GitHub
Deep Wiki
Context7

Getting Started

stingus/jira-bundle is a Symfony bundle that wires up an OAuth 1.0a–signed HTTP client for talking to Jira (typically Jira Server / Data Center, where 1.0a is still the norm). The first thing to do is check compatibility before anything else — the last tagged release is from late 2019, so expect it to target Symfony 3.4/4.x and PHP 7.x. If you're on Symfony 5+, expect to fork the repo and bump composer.json constraints (the surface area is small, so this is usually a 15-minute patch).

Minimal steps:

  1. composer require stingus/jira-bundle (or dev-main if you've forked).
  2. Register the bundle — config/bundles.php on Flex projects, or AppKernel::registerBundles() on Symfony 3.
  3. Create a YAML config (config/packages/stingus_jira.yaml) with your consumer key/secret, token/secret, and Jira base URL. Pull every value from environment variables — see Gotchas.
  4. Verify auth with a single call to /rest/api/2/myself. This is the fastest way to confirm signing works before you build anything on top of it.

Where to look first, in order:

  • DependencyInjection/Configuration.php — the authoritative list of config keys and defaults.
  • Resources/config/services.xml (or .yaml) — the actual service IDs you'll inject.
  • DependencyInjection/*Extension.php — how config maps onto the client.
  • StingusJiraBundle.php — confirms it's a thin DI wrapper, not a full API SDK.

First real use case: inject the Jira client into a small custom service and issue a GET /rest/api/2/issue/{key} call. If that 200s with a JSON payload, you have working OAuth 1.0a plumbing and can build up from there.

Implementation Patterns

Wrap the client, don't scatter it. The bundle hands you a signed HTTP client, not a domain API. Create your own App\Jira\JiraClient that injects the bundle's client and exposes methods like createIssue(Project $p, array $fields), transition(IssueKey $k, string $name), searchJql(string $jql). If you ever swap to a different integration approach (Jira Cloud + API tokens, or bitly/oauth1 directly), you change one class.

Split consumer credentials from token credentials. OAuth 1.0a has two layers: the application (consumer key/secret) and the user (token/token secret). For multi-tenant or per-user integrations you need to store each user's token pair and build a signed client per user. The bundle typically configures a single client from YAML — so if you're doing per-user auth, you won't get much from the bundle beyond the signing logic and will want to instantiate clients dynamically.

Common endpoints you'll write within a week:

  • GET /rest/api/2/myself — health check.
  • POST /rest/api/2/issue — create an issue from a webhook payload (e.g. a customer support ticket).
  • POST /rest/api/2/issue/{key}/comment — sync comments both ways.
  • POST /rest/api/2/issue/{key}/transitions — move issues through workflow (two-step: GET available transitions, then POST the id).
  • GET /rest/api/2/search?jql=… — polling for state changes when webhooks aren't available.

Pair with Jira webhooks, don't poll. The bundle is for outbound calls. Use Jira's outgoing webhooks to tell your app "issue updated" — then respond with API calls. Polling JQL on a cron is a fallback; it's slow and hits rate limits quickly on busy instances.

Integration tips:

  • Register your wrapper service and inject it via constructor. Don't call $container->get() inline.
  • If you need request-level logging, decorate the bundle's client service (Symfony's decorates: key) rather than editing vendor code. Redact the Authorization header before logging — OAuth 1.0a signatures are bearer-equivalent.
  • Configure a timeout and retry policy on the underlying HTTP client. Jira's UI is fast; its REST API is not always.

Gotchas and Tips

This package is effectively unmaintained. 5 stars, 0 dependents, no release since 2019. Treat it as a reference implementation, not a long-term dependency. Fork it into your own namespace, bump constraints, and pin to your fork. You'll be doing this anyway if you're on a modern Symfony.

OAuth 1.0a signing is fragile. The signature is computed over a canonicalized request — method, URL, sorted and percent-encoded parameters, and the signing key derived from consumer secret + token secret. Failure modes:

  • Any mismatch (trailing slash, port in URL, a non-encoded + in query params) → 401 oauth_problem=signature_invalid.
  • Clock skew → 401 oauth_problem=timestamp_refused. Ensure NTP is running on the host.
  • Nonce reuse → 401 oauth_problem=nonce_used. If you retry a request, sign it fresh.

Jira Cloud is not the target. Cloud has moved to API tokens and OAuth 2.0. If you're integrating with Cloud, you probably don't want this bundle at all — an API token with basic auth (or OAuth 2.0 3LO) is simpler and supported. This bundle is for Server/Data Center self-hosted installs.

Secrets leak trivially. The consumer secret and token secret are effectively bearer credentials. Keep them out of committed YAML and out of logs. In Symfony, prefer %env(JIRA_CONSUMER_SECRET)% and use a .env.local that isn't committed.

Guzzle version is the real constraint. Bundles of this era typically pull in guzzlehttp/guzzle 5.x or 6.x, or rely on eightpoints/guzzle-bundle. Neither plays well with Symfony's HttpClient, and Guzzle 5 is EOL. When you fork, move to Guzzle 7 + guzzle/plugin-oauth — but note that plugin was removed in Guzzle 7, so plan on either using an out-of-tree OAuth 1.0a signer or implementing the ~40 lines of signing yourself.

Error handling is your job. The bundle won't normalize Jira's error envelope. Parse errorMessages and errors from 400 responses (Jira returns both, sometimes with per-field detail). Distinguish 401 (auth/signing) from 403 (auth OK, permission missing) from 404 (bad key or no browse permission — Jira deliberately conflates these).

Extension points are limited. There's no event system or plugin layer — it's a DI wrapper around a client. If you need custom behavior, decorate the service, or skip the bundle and copy its signing logic into your own client. Given the size of the bundle and the lack of maintenance, the latter is often the pragmatic choice.

Debugging checklist when a call fails:

  1. curl the same endpoint with the same params — if curl works and the bundle doesn't, it's signing.
  2. Log the unsigned base string and normalized parameter list; compare to what the OAuth debug tool computes.
  3. Confirm the URL registered with the Jira application link exactly matches (scheme, host, path prefix) what you're sending.
  4. Check token isn't revoked in Jira's Consumer setup.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console