<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Orbit A</title>
    <description>The latest articles on Forem by Orbit A (@orbit-a-devteam).</description>
    <link>https://forem.com/orbit-a-devteam</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3807956%2F401d5c1d-ad20-40c3-996a-30507b3d5cd1.png</url>
      <title>Forem: Orbit A</title>
      <link>https://forem.com/orbit-a-devteam</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/orbit-a-devteam"/>
    <language>en</language>
    <item>
      <title>Bridging the Gap Between Appium and Jira: A Native Approach Using Atlassian Forge</title>
      <dc:creator>Orbit A</dc:creator>
      <pubDate>Tue, 14 Apr 2026 12:01:10 +0000</pubDate>
      <link>https://forem.com/orbit-a-devteam/bridging-the-gap-between-appium-and-jira-a-native-approach-using-atlassian-forge-32jg</link>
      <guid>https://forem.com/orbit-a-devteam/bridging-the-gap-between-appium-and-jira-a-native-approach-using-atlassian-forge-32jg</guid>
      <description>&lt;h2&gt;
  
  
  Introduction: The Context-Switching Problem
&lt;/h2&gt;

&lt;p&gt;In mobile automation, the distance between “a test failed” and “a developer fixed it” is often measured in manual steps. You run your Appium suite, wait for the CI/CD pipeline to finish, and then embark on a quest through thousands of lines of logs to find the culprit.&lt;/p&gt;

&lt;p&gt;At &lt;strong&gt;Orbit A&lt;/strong&gt;, we’ve seen this bottleneck slow down teams repeatedly. Having already built reporting tools for &lt;strong&gt;Playwright, Cypress, JMeter and k6&lt;/strong&gt;, we set out to solve the mobile reporting puzzle. Our goal was to create a system where test results aren’t just an artifact in a CI console, but a living part of a Jira Issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Architecture: Why Forge?
&lt;/h2&gt;

&lt;p&gt;Most Jira integrations rely on external backends. You send data to a third-party server, which then talks to Jira via REST API.&lt;br&gt;
We decided to go &lt;strong&gt;native&lt;/strong&gt;. By building on &lt;strong&gt;Atlassian Forge&lt;/strong&gt;, we eliminated the “middleman” entirely.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data Residency: Your test metrics never leave the Atlassian infrastructure. They are stored in Forge Storage, complying with enterprise security standards.&lt;/li&gt;
&lt;li&gt;Security: There are no external databases to breach. Authentication is handled via a tenant-specific Security Token, ensuring that only your authorized CI environment can push updates.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step-by-Step: Integrating Appium with Jira
&lt;/h2&gt;

&lt;p&gt;To make this work for any mobile project, we focused on WebdriverIO (WDIO) as the primary framework. Here is how we structured the integration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Preparing the Environment&lt;/strong&gt;&lt;br&gt;
First, you need the standard WDIO stack. If you are starting fresh or adding to an existing project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @wdio/cli @wdio/local-runner @wdio/mocha-framework @wdio/spec-reporter &lt;span class="nt"&gt;--save-dev&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. The Custom Reporter Logic&lt;/strong&gt;&lt;br&gt;
The core of the integration is a custom reporter. We’ve designed a template that handles the collection of test states (passed, failed, skipped) and sends a single, optimized payload at the end of the run.&lt;/p&gt;

&lt;p&gt;Inside your project, create wdio-jira-reporter.js. Here is the logic we implemented to ensure data integrity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;WDIOReporter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@wdio/reporter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JiraReporter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;WDIOReporter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;assign&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="c1"&gt;// We pull the Jira ID from an env variable to keep it dynamic&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;issueId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;issueId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JIRA_ISSUE_ID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isDone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;onTestPass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;passed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_duration&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nf"&gt;onTestFail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_duration&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;onRunnerEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isDone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;failedCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR_ORBIT_A_TOKEN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Generated in Jira Config&lt;/span&gt;
            &lt;span class="na"&gt;issueId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;issueId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;failedCount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;passed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;passed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testResults&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;passed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;failedCount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;testResults&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;YOUR_FORGE_WEBTRIGGER_URL&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[Orbit A] ✅ Results synced to Jira.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[Orbit A] ❌ Sync failed:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isDone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JiraReporter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Execution via CLI&lt;/strong&gt;&lt;br&gt;
Linking a run to a specific Jira ticket is handled via environment variables. This makes it incredibly easy to use within GitHub Actions, GitLab CI, or Bitrise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;JIRA_ISSUE_ID&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;MOB-10010 npx wdio run wdio.conf.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;&lt;strong&gt;NotaBene! How to find the Numeric Issue ID:&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the Jira Issue you are testing.&lt;/li&gt;
&lt;li&gt;Look at the URL in your browser.
— If you are on a Board: You will see ...&amp;amp;selectedIssue=10010. The number is the ID.
— If you are in the direct issue view: You can navigate to Jira ticket → click ‘Actions’ button → click ‘Export XML’ → copy value of ‘key_id’, i.e. {some-name} (here you’ll need to copy 10010)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;The Result: A Unified QA View&lt;/strong&gt;&lt;br&gt;
When the payload hits the Forge Webtrigger, the app validates the token and stores the metrics. Inside Jira, we provide a custom Issue Panel.&lt;br&gt;
When a developer or manager opens 10010, they don’t see a link to a log file - they see a rendered table.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjywykqmslqfciocy4c7b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjywykqmslqfciocy4c7b.png" alt="hero snapshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;High-level metrics: Overall status and duration.&lt;/li&gt;
&lt;li&gt;Test Breakdown: A searchable list of all test cases within that specific run.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Key Takeaway:&lt;/em&gt;&lt;/strong&gt; By surfacing this data directly in the ticket, we’ve seen teams reduce “clarification time” between QA and Dev by up to 40%.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: The Orbit A Ecosystem
&lt;/h2&gt;

&lt;p&gt;The release of Appium Test Results for Jira completes our current vision of a unified QA reporting stack. Whether you are running Cypress or Playwright for web, JMeter or k6 for performance, or Appium for mobile, you now have a single, secure way to report back to Jira.&lt;/p&gt;

&lt;p&gt;Automated testing shouldn’t just find bugs; it should make them easier to fix.&lt;/p&gt;

&lt;p&gt;Explore the Orbit A suite on the Atlassian Marketplace:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://marketplace.atlassian.com/apps/1364170176/playwright-results-for-jira?hosting=cloud&amp;amp;tab=overview" rel="noopener noreferrer"&gt;Playwright Results for Jira&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://marketplace.atlassian.com/apps/3720597310/appium-test-results-for-jira?hosting=cloud&amp;amp;tab=overview" rel="noopener noreferrer"&gt;Appium Test Results for Jira&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://marketplace.atlassian.com/apps/2125309025/cypress-test-results-for-jira?hosting=cloud&amp;amp;tab=overview" rel="noopener noreferrer"&gt;Cypress Test Results for Jira&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://marketplace.atlassian.com/apps/2490465905/k6-performance-analytics-for-jira?hosting=cloud&amp;amp;tab=overview" rel="noopener noreferrer"&gt;k6 Performance Analytics for Jira&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;a href="https://marketplace.atlassian.com/apps/611477863/jmeter-performance-analytics-for-jira?hosting=cloud&amp;amp;tab=overview" rel="noopener noreferrer"&gt;JMeter Performance Analytics for Jira&lt;/a&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you found this helpful, follow &lt;strong&gt;&lt;a href="https://www.linkedin.com/company/orbit-a-apps/" rel="noopener noreferrer"&gt;Orbit A on LinkedIn&lt;/a&gt;&lt;/strong&gt;. We are building a suite of native Atlassian apps for QA and DevOps teams!&lt;/p&gt;

&lt;p&gt;Happy testing,&lt;br&gt;
&lt;strong&gt;The Orbit A Team&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>appium</category>
      <category>mobile</category>
      <category>webriverio</category>
      <category>automation</category>
    </item>
    <item>
      <title>The Ultimate Guide to Integrating JMeter with Jira CI/CD</title>
      <dc:creator>Orbit A</dc:creator>
      <pubDate>Thu, 19 Mar 2026 12:29:05 +0000</pubDate>
      <link>https://forem.com/orbit-a-devteam/the-ultimate-guide-to-integrating-jmeter-with-jira-cicd-3m3k</link>
      <guid>https://forem.com/orbit-a-devteam/the-ultimate-guide-to-integrating-jmeter-with-jira-cicd-3m3k</guid>
      <description>&lt;p&gt;&lt;strong&gt;JMeter is the undisputed king of load testing. It’s powerful, flexible, and handles massive scale. But let’s be honest: sharing JMeter results with your team feels like it’s still 2010.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Usually, the workflow goes like this: The test finishes. You generate an HTML Dashboard. You zip the folder. You open Jira, find the right ticket, and attach a heavy .zip file or a massive .jtl CSV. Your developers and Product Managers then have to download it, unzip it, and try to understand what went wrong.&lt;/p&gt;

&lt;p&gt;Performance testing shouldn’t create data silos. When your team is working on a Jira ticket, they need the core performance metrics (Pass/Fail, Response Times, Error Rates) right there on the screen.&lt;br&gt;
Let’s look at how to stop context-switching and push JMeter results directly into Atlassian Jira.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hard Way: Custom Plugins and CI/CD Scripts
&lt;/h2&gt;

&lt;p&gt;Many QA teams try to automate this by writing complex bash scripts in Jenkins or GitHub Actions. They use tools to parse the .jtl file, authenticate with Jira's REST API, and post a messy text comment into the issue.&lt;/p&gt;

&lt;p&gt;It takes days to set up, tokens expire, and the formatting is always hard to read.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Smart Way: Direct Webhooks via tearDown Thread Group
&lt;/h2&gt;

&lt;p&gt;Instead of reinventing the wheel, our team at Orbit A released the &lt;a href="https://marketplace.atlassian.com/apps/611477863/jmeter-performance-analytics-for-jira?hosting=cloud&amp;amp;tab=overview" rel="noopener noreferrer"&gt;&lt;strong&gt;JMeter Performance Analytics for Jira&lt;/strong&gt;&lt;/a&gt;. It’s a zero-config Atlassian Forge app that allows you to push JMeter metrics directly into the Jira Issue Panel using a simple Webhook.&lt;/p&gt;

&lt;p&gt;No custom plugins to install. No Java coding required. Just a native JMeter HTTP Request. Here is how to set it up in 2 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-Step Guide
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Install the App&lt;/strong&gt;&lt;br&gt;
Head over to the Atlassian Marketplace and install the &lt;a href="https://marketplace.atlassian.com/apps/611477863/jmeter-performance-analytics-for-jira?hosting=cloud&amp;amp;tab=overview" rel="noopener noreferrer"&gt;&lt;strong&gt;JMeter Performance Analytics for Jira&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Generate Your Webhook&lt;/strong&gt;&lt;br&gt;
Go to your Jira Apps menu and open the JMeter to Jira Config page. The app will instantly generate your unique Webhook URL and Secret Token.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fufe7d28zw77pqq0asc5o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fufe7d28zw77pqq0asc5o.png" alt="config page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Add a tearDown Thread Group in JMeter&lt;/strong&gt;&lt;br&gt;
JMeter has a special feature called the tearDown Thread Group, which executes after your main load test finishes. This is the perfect place to send your results!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Right-click your Test Plan -&amp;gt; Add -&amp;gt; Threads (Users) -&amp;gt; tearDown Thread Group.&lt;/li&gt;
&lt;li&gt;Inside it, add an JSR223 Sampler paste this script:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;groovy.json.JsonBuilder&lt;/span&gt;

&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"MY_DETAILED_STATS"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stats&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"No stats found in MY_DETAILED_STATS! Check your Listener."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;reportList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;[]&lt;/span&gt;
&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;grandTotalTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;grandTotalCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;grandTotalErrors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

&lt;span class="kt"&gt;boolean&lt;/span&gt; &lt;span class="n"&gt;stepFailed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;

&lt;span class="n"&gt;stats&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;each&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;avg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;totalTime&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;
    &lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;errRate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
    &lt;span class="n"&gt;errRate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;round&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errRate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;100.0&lt;/span&gt;

    &lt;span class="n"&gt;reportList&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;([&lt;/span&gt;
        &lt;span class="nl"&gt;label:&lt;/span&gt; &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;avg:&lt;/span&gt; &lt;span class="n"&gt;avg&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;errorRate:&lt;/span&gt; &lt;span class="n"&gt;errRate&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
        &lt;span class="nl"&gt;count:&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;
    &lt;span class="o"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;errRate&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;stepFailed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;warn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Step [${label}] failed with ${errRate}% errors"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;grandTotalTime&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;totalTime&lt;/span&gt;
    &lt;span class="n"&gt;grandTotalCount&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;count&lt;/span&gt;
    &lt;span class="n"&gt;grandTotalErrors&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;errors&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;long&lt;/span&gt; &lt;span class="n"&gt;finalAvg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;grandTotalCount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;grandTotalTime&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;grandTotalCount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;finalErr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;grandTotalCount&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt;&lt;span class="n"&gt;grandTotalErrors&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;grandTotalCount&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;finalErr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;round&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;finalErr&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;100.0&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;100.0&lt;/span&gt;

&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="n"&gt;finalStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"PASS"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;finalErr&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;finalAvg&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;stepFailed&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;finalStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"FAIL"&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kt"&gt;def&lt;/span&gt; &lt;span class="n"&gt;jsonBuilder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;JsonBuilder&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reportList&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"JSON_DETAILS_STRING"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jsonBuilder&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toString&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt;
&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"FINAL_AVG"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;finalAvg&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"FINAL_ERR"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;String&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;finalErr&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;
&lt;span class="n"&gt;props&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"FINAL_STATUS"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;finalStatus&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Final Stats: Avg=${finalAvg}ms, TotalErr=${finalErr}%, Status=${finalStatus}"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"Detailed report prepared for ${reportList.size()} items."&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Also in tearDown Thread Group add HTTP Request Sampler.&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set the Method to POST and paste your Jira Webhook URL.&lt;/li&gt;
&lt;li&gt;Add an HTTP Header Manager and set Content-Type to application/json.&lt;/li&gt;
&lt;li&gt;In the Body Data of your HTTP Request, paste this JSON payload:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${__P(token, YOUR_TOKEN)}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="nl"&gt;"issueId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${__P(issueId, ISSUE_ID)}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
    &lt;/span&gt;&lt;span class="nl"&gt;"avgResponseTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;__P(FINAL_AVG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"errorRate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;__P(FINAL_ERR&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${__P(FINAL_STATUS, PASS)}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"details"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;__P(JSON_DETAILS_STRING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Also, don’t forget to fill in:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Server name or IP field with your url like ‘{uuid-from-jira-config-page}.hello.atlassian-dev.net&lt;/li&gt;
&lt;li&gt;Path filed with your url’s path part, like : ‘/x1/Z-U7s9ZwttETBesD2ri07HJYBU’&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;How to find the Numeric Issue ID:&lt;/strong&gt;&lt;br&gt;
Open the Jira Issue you are testing.&lt;br&gt;
Look at the URL in your browser.&lt;br&gt;
— If you are on a Board: You will see ...&amp;amp;selectedIssue=10023. The number is the ID.&lt;br&gt;
— If you are in the direct issue view: You can navigate to Jira ticket → click ‘Actions’ button → click ‘Export XML’ → copy value of ‘key_id’, i.e. KAN-7 (here you’ll need to copy 10134)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmckck543un1169bub63x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmckck543un1169bub63x.png" alt="jira numeric id"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: You can trigger this script in your GitHub Actions, GitLab CI, or Jenkins pipeline dynamically passing the current Jira Issue ID based on the branch name!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Result: Performance at a Glance
&lt;/h2&gt;

&lt;p&gt;The moment your JMeter test finishes, the HTTP request fires, and your developers will instantly see the core metrics right on the Jira issue panel:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxhhdr6wlm7bifp0302ej.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxhhdr6wlm7bifp0302ej.png" alt="main panel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They can also click to expand the details and see the exact breakdown of your HTTP Samplers:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs9qqni08xo83yj7irijp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs9qqni08xo83yj7irijp.png" alt="detailed panel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By pushing JMeter results directly into Jira, you eliminate ZIP files, reduce manual reporting, and give developers immediate feedback exactly where they track their work.&lt;/p&gt;

&lt;p&gt;👉 Try &lt;a href="https://marketplace.atlassian.com/apps/611477863/jmeter-performance-analytics-for-jira?hosting=cloud&amp;amp;tab=overview" rel="noopener noreferrer"&gt;&lt;strong&gt;JMeter Performance Analytics for Jira&lt;/strong&gt;&lt;/a&gt; on the &lt;strong&gt;Atlassian Marketplace&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;If you found this helpful, follow &lt;a href="https://www.linkedin.com/company/orbit-a-apps/?viewAsMember=true" rel="noopener noreferrer"&gt;Orbit A on LinkedIn&lt;/a&gt;. We are building a suite of native Atlassian apps for QA and DevOps teams!&lt;/p&gt;

</description>
      <category>jmeter</category>
      <category>performance</category>
      <category>devops</category>
      <category>testing</category>
    </item>
    <item>
      <title>Stop Sharing Grafana Links: How to Send k6 Load Test Results Directly to Jira</title>
      <dc:creator>Orbit A</dc:creator>
      <pubDate>Thu, 12 Mar 2026 12:34:38 +0000</pubDate>
      <link>https://forem.com/orbit-a-devteam/stop-sharing-grafana-links-how-to-send-k6-load-test-results-directly-to-jira-fh6</link>
      <guid>https://forem.com/orbit-a-devteam/stop-sharing-grafana-links-how-to-send-k6-load-test-results-directly-to-jira-fh6</guid>
      <description>&lt;p&gt;&lt;strong&gt;Your k6 load test just finished. The API survived 10,000 virtual users. Now, how do you communicate that success to the product manager and developers?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Usually, it goes like this: The performance engineer takes a screenshot of the terminal, exports a CSV, or drops a Grafana dashboard link into a Jira comment. The developer sees the link, realizes they have to log into another system, and ignores it.&lt;/p&gt;

&lt;p&gt;Performance testing shouldn't live in a silo. When developers are working on a Jira ticket to "Optimize Checkout API," they need the performance metrics right there, inside the ticket.&lt;/p&gt;

&lt;p&gt;Let's look at how to stop context-switching and push k6 results directly into Atlassian Jira.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hard Way: Custom Pipelines and API Tokens
&lt;/h2&gt;

&lt;p&gt;Many DevOps teams try to build this themselves. They write custom scripts to parse the k6 JSON output, authenticate with Jira's REST API using user tokens (which eventually expire), and struggle to format the data into readable tables inside Jira comments.&lt;/p&gt;

&lt;p&gt;It takes days to build and constantly requires maintenance.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Smart Way: Direct Jira Issue Webhooks
&lt;/h2&gt;

&lt;p&gt;Instead of building it from scratch, our team at Orbit A released the &lt;a href="https://marketplace.atlassian.com/apps/2490465905/k6-performance-analytics-for-jira?hosting=cloud&amp;amp;tab=overview" rel="noopener noreferrer"&gt;k6 Performance Analytics for Jira&lt;/a&gt;. It's a zero-config Atlassian Forge app that allows you to push k6 performance metrics directly into the Jira Issue Panel using a simple Webhook.&lt;/p&gt;

&lt;p&gt;It natively hooks into the k6 handleSummary() callback, requiring no external dependencies. Here is how to set it up in under 2 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-Step Guide
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Install the App&lt;/strong&gt;&lt;br&gt;
Head over to the Atlassian Marketplace and install the &lt;strong&gt;&lt;a href="https://marketplace.atlassian.com/apps/2490465905/k6-performance-analytics-for-jira?hosting=cloud&amp;amp;tab=overview" rel="noopener noreferrer"&gt;k6 Performance Analytics for Jira&lt;/a&gt;&lt;/strong&gt; (it's free to try).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Generate Your Webhook&lt;/strong&gt;&lt;br&gt;
Go to your Jira Apps menu and open the &lt;strong&gt;k6 to Jira Config page&lt;/strong&gt;. The app will instantly and securely generate your unique:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Webhook URL.&lt;/li&gt;
&lt;li&gt;Secret Token.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgcpflmjc0ajx0kur4hkp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgcpflmjc0ajx0kur4hkp.png" alt="config page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Add handleSummary to Your k6 Script&lt;/strong&gt;&lt;br&gt;
k6 has a brilliant built-in feature called handleSummary, which runs at the very end of your test. You simply append this code to your existing k6 script.&lt;/p&gt;

&lt;p&gt;Here is the secure, production-ready script. It accurately calculates error rates, pushes the data to Jira, and still preserves your standard terminal output!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reporterCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`import http from 'k6/http';
import { textSummary } from 'https://jslib.k6.io/k6-summary/0.0.2/index.js';

export default function () {
  http.get('https://test-api.k6.io');
}

export function handleSummary(data) {
  const issueId = __ENV.JIRA_ISSUE_ID;

  const avgResponseTime = data.metrics.http_req_duration ? data.metrics.http_req_duration.values.avg : 0;
  const reqCount = data.metrics.http_reqs ? data.metrics.http_reqs.values.count : 0;

  const errorRate = data.metrics.http_req_failed ? (data.metrics.http_req_failed.values.rate * 100) : 0;

  const status = (errorRate &amp;gt; 1 || avgResponseTime &amp;gt; 5000) ? "FAIL" : "PASS";

  const payload = JSON.stringify({
    token: "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;", 
    issueId: issueId,
    status: status,
    avgResponseTime: avgResponseTime,
    errorRate: errorRate,
    transactions: [
      { 
        name: "Total API Requests", 
        avgTime: avgResponseTime, 
        errorRate: errorRate,
        requests: reqCount 
      }
    ]
  });

  if (!issueId) {
     console.log('&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n[Jira Reporter] ⚠️ No JIRA_ISSUE_ID provided. Skipping Jira update.');
     return { 'stdout': textSummary(data, { indent: ' ', enableColors: true }) };
  }

  console.log('&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;n[Jira Reporter] Sending performance results to Jira issue: ' + issueId);

  const res = http.post('&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;webhookUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;', payload, {
    headers: { 'Content-Type': 'application/json' },
  });

  if (res.status === 200) {
    console.log('[Jira Reporter] ✅ Successfully pushed results to Jira!');
  } else {
    console.log('[Jira Reporter] ❌ Failed to push to Jira. Status: ' + res.status);
  }

  return {
    'stdout': textSummary(data, { indent: ' ', enableColors: true }),
  };
}`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: Trigger this script in your CI/CD pipeline like this: k6 run -e JIRA_ISSUE_ID=PROJ-123 script.js&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;(Important: Please ensure issueId is the numeric ID, e.g., 10023, not the Key like PROJ-1)&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to find the Numeric Issue ID:&lt;/strong&gt;&lt;br&gt;
Open the Jira Issue you are testing.&lt;br&gt;
Look at the URL in your browser.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you are on a Board: You will see ...&amp;amp;selectedIssue=10023. The number is the ID.&lt;/li&gt;
&lt;li&gt;If you are in the direct issue view: You can navigate to Jira ticket → click 'Actions' button → click 'Export XML' → copy value of 'key_id', i.e. KAN-7 (here you'll need to copy 10134)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhvcycn2c0rrwdz0c2e1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhvcycn2c0rrwdz0c2e1.png" alt="numeric jira issue example"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: You can trigger this script in your GitHub Actions, GitLab CI, or Jenkins pipeline dynamically passing the current Jira Issue ID based on the branch name!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Result: Performance at a Glance
&lt;/h2&gt;

&lt;p&gt;The moment your k6 load test finishes, the developer or SRE opening the Jira ticket will instantly see the core metrics right on the issue panel:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zhh8zw90qtp8djr9imz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zhh8zw90qtp8djr9imz.png" alt="main panel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They can also click to expand the details and see the exact breakdown of transactions:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlvxgt9ywle44yoiak4i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqlvxgt9ywle44yoiak4i.png" alt="detailed panel"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By bridging the gap between performance testing tools like k6 and project management tools like Jira, you eliminate data silos. QA engineers stop acting as messenger pigeons, and developers get immediate feedback exactly where they track their work.&lt;/p&gt;

&lt;p&gt;👉 [&lt;a href="https://marketplace.atlassian.com/apps/2490465905/k6-performance-analytics-for-jira?hosting=cloud&amp;amp;tab=overview" rel="noopener noreferrer"&gt;Try k6 Performance Analytics for Jira on the Atlassian Marketplace&lt;/a&gt;]&lt;/p&gt;

&lt;p&gt;If you found this helpful, be sure to follow &lt;strong&gt;&lt;a href="https://www.linkedin.com/company/orbit-a-apps/" rel="noopener noreferrer"&gt;Orbit A on LinkedIn&lt;/a&gt;&lt;/strong&gt;. We are building a suite of native Atlassian apps for QA and DevOps teams, including integrations for Playwright, Cypress, and JMeter!&lt;/p&gt;

</description>
      <category>k6</category>
      <category>performance</category>
      <category>devops</category>
      <category>testing</category>
    </item>
    <item>
      <title>How to Send Cypress Results Directly to Jira Tickets</title>
      <dc:creator>Orbit A</dc:creator>
      <pubDate>Wed, 11 Mar 2026 15:11:07 +0000</pubDate>
      <link>https://forem.com/orbit-a-devteam/how-to-send-cypress-results-directly-to-jira-tickets-294d</link>
      <guid>https://forem.com/orbit-a-devteam/how-to-send-cypress-results-directly-to-jira-tickets-294d</guid>
      <description>&lt;p&gt;&lt;strong&gt;Your Cypress E2E suite just finished running in your CI/CD pipeline. It caught a regression. Great job!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But what happens next? If your team is like most, the QA engineer has to open the GitHub Actions or Jenkins logs, figure out which spec failed, take a screenshot, and manually paste it into the developer’s Jira ticket with a comment like: “&lt;em&gt;Hey, this broke in the latest build. Here is the link to the logs.&lt;/em&gt;”&lt;/p&gt;

&lt;p&gt;Cypress is an incredible tool for writing reliable End-to-End tests. But when it comes to communicating those results across the team, the feedback loop is often broken. Developers and Product Managers live in Jira, not in your CI logs.&lt;/p&gt;

&lt;p&gt;Let’s look at how to bridge this gap and push Cypress results exactly where the work is happening.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Old Way: Manual Links and Expensive Dashboards
&lt;/h2&gt;

&lt;p&gt;Historically, teams have tried to solve this in a few ways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pasting links: Manually linking to CI logs or HTML reports (like Mochawesome) in Jira comments. It’s tedious, and nobody actually clicks those links.&lt;/li&gt;
&lt;li&gt;Building custom integrations: Writing complex Node.js scripts using Atlassian API tokens to format Jira comments. These scripts take days to build and constantly break when tokens expire.&lt;/li&gt;
&lt;li&gt;Paying for external dashboards: Using premium cloud dashboards that developers rarely log into anyway because it forces them to context-switch out of Atlassian.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Smart New Way: Direct Jira Issue Webhooks
&lt;/h2&gt;

&lt;p&gt;Software quality should be visible right inside the Jira ticket that the developer is actively working on.&lt;/p&gt;

&lt;p&gt;To solve this, our team at Orbit A built the Cypress Test Results for Jira -&amp;gt; &lt;a href="https://marketplace.atlassian.com/apps/2125309025/cypress-test-results-for-jira?hosting=cloud&amp;amp;tab=overview&amp;amp;showOnlyPublic=true" rel="noopener noreferrer"&gt;Link to Atlassian Marketplace Is Here!&lt;/a&gt; It is a native, zero-config Atlassian Forge app that allows you to push Cypress test results directly into the Jira Issue Panel using a simple Webhook.&lt;/p&gt;

&lt;p&gt;No API tokens to manage. No complex formatting. Just a simple JSON payload. Here is how to set it up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-Step Guide
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Install the App&lt;/strong&gt;&lt;br&gt;
Head over to the Atlassian Marketplace and install the Cypress Test Results for Jira (it’s free to try).&lt;br&gt;
&lt;strong&gt;Step 2: Generate Your Webhook&lt;/strong&gt;&lt;br&gt;
Go to your Jira Apps menu and open the Cypress to Jira page. The app will securely generate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Webhook URL.&lt;/li&gt;
&lt;li&gt;A Secret Token.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frofi4hm6jfsq0nkxogyq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frofi4hm6jfsq0nkxogyq.png" alt="config page"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Add a POST Request to Your CI Pipeline&lt;/strong&gt;&lt;br&gt;
Once your Cypress tests finish running, you usually have a JSON report (for example, generated by Mochawesome or a custom Cypress reporter). You can simply parse that report and send it to Jira using Node.js or &lt;code&gt;curl&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is an example of a simple Node.js script you can run in your after:run hook or as a separate CI step:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// cypress-jira-reporter.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Mocha&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mocha&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;EVENT_RUN_END&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;EVENT_TEST_PASS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;EVENT_TEST_FAIL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;EVENT_TEST_PENDING&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Mocha&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;constants&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;JiraReporter&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Mocha&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reporters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Base&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;reporterOptions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reporterOptions&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;issueId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reporterOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;issueId&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JIRA_ISSUE_ID&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;webhookUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reporterOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;webhookUrl&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JIRA_WEBHOOK_URL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;reporterOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JIRA_WEBHOOK_TOKEN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;passed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;failed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;skipped&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tests&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

    &lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;EVENT_TEST_PASS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;passed&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;passed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;EVENT_TEST_FAIL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failed&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;EVENT_TEST_PENDING&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;skipped&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;skipped&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;EVENT_RUN_END&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;duration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startTime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;overallStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;failed&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;failed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;passed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;issueId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;issueId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;overallStatus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;tests&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;

      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;webhookUrl&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;issueId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;[Jira Reporter] ⚠️ Missing Webhook URL, Token, or Issue ID. Skipping Jira update.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;[Jira Reporter] Sending results to Jira issue:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;issueId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;webhookUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[Jira Reporter] ✅ Successfully pushed results to Jira!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[Jira Reporter] ❌ Error sending payload to Jira:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JiraReporter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(Important: Please ensure issueId is the numeric ID, e.g., 10023, not the Key like PROJ-1)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How to find the Numeric Issue ID&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open the Jira Issue you are testing.&lt;/li&gt;
&lt;li&gt;Look at the URL in your browser.&lt;/li&gt;
&lt;li&gt;If you are on a Board: You will see ...&amp;amp;selectedIssue=10023. The number is the ID.&lt;/li&gt;
&lt;li&gt;If you are in the direct issue view: You can navigate to Jira ticket → click ‘Actions’ button → click ‘Export XML’ → copy value of ‘key_id’, i.e. KAN-7 (here you’ll need to copy 10134)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvnjq21rxnh4yss58g787.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvnjq21rxnh4yss58g787.png" alt="jira numeric issue id"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: You can trigger this script in your GitHub Actions, GitLab CI, or Jenkins pipeline dynamically passing the current Jira Issue ID based on the branch name!&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Result: Total Visibility
&lt;/h2&gt;

&lt;p&gt;The moment your CI pipeline finishes, any developer or PM opening the Jira ticket will instantly see this on the right-side panel:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1r9esfmh2tht6mhflis.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm1r9esfmh2tht6mhflis.png" alt="hero screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They don’t need to ask for test results history. They can click on the Select Run tab to see 5 latest test runs and their results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqn45wtc4rpnc7zgxh7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyqn45wtc4rpnc7zgxh7g.png" alt="detailed screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By integrating Cypress directly with Jira, you eliminate context-switching. QA engineers stop acting as log-couriers, and developers get immediate feedback exactly where they track their work.&lt;/p&gt;

&lt;p&gt;👉 Try Cypress Test Results for Jira on the Atlassian Marketplace -&amp;gt; &lt;a href="https://marketplace.atlassian.com/apps/2125309025/cypress-test-results-for-jira?hosting=cloud&amp;amp;tab=overview&amp;amp;showOnlyPublic=true" rel="noopener noreferrer"&gt;Link to Atlassian Marketplace!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you found this helpful, be sure to follow &lt;strong&gt;&lt;a href="https://www.linkedin.com/company/orbit-a-apps/" rel="noopener noreferrer"&gt;Orbit A on LinkedIn&lt;/a&gt;&lt;/strong&gt;. We are building a suite of tools to bridge the gap between testing and project management, including native integrations for Playwright, k6, and JMeter!&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>aqa</category>
      <category>jira</category>
      <category>testing</category>
    </item>
    <item>
      <title>The Ultimate Guide to Tracking Playwright Automation Results in Jira Issues</title>
      <dc:creator>Orbit A</dc:creator>
      <pubDate>Thu, 05 Mar 2026 13:19:03 +0000</pubDate>
      <link>https://forem.com/orbit-a-devteam/the-ultimate-guide-to-tracking-playwright-automation-results-in-jira-issues-a3c</link>
      <guid>https://forem.com/orbit-a-devteam/the-ultimate-guide-to-tracking-playwright-automation-results-in-jira-issues-a3c</guid>
      <description>&lt;p&gt;You wrote a beautiful, rock-solid Playwright test suite. It caught a critical bug in the CI pipeline. Splendid!&lt;/p&gt;

&lt;p&gt;…And then you spend the next 15 minutes explaining to the developer which pipeline ran, where to find the logs, and manually pasting screenshots of the failed assertions into a Jira ticket. Not awesome.&lt;/p&gt;

&lt;p&gt;If your team uses Playwright, you know it’s incredibly fast and reliable. But communicating those test results across the team is still a manual, context-switching nightmare. Software quality shouldn’t live in a siloed CI/CD black hole — it should live exactly where your team tracks their work: &lt;strong&gt;in Jira.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s look at how to fix this workflow once and for all.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hard Way: Custom Scripts and Jira API Nightmares
&lt;/h2&gt;

&lt;p&gt;Usually, when QA engineers or DevOps teams try to automate sending test results to Jira, they go down the rabbit hole of building custom integrations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Creating Atlassian API tokens (which eventually expire and break the pipeline).&lt;/li&gt;
&lt;li&gt;Writing complex Node.js scripts to parse Playwright’s JSON reports.&lt;/li&gt;
&lt;li&gt;Wrestling with Jira’s Atlassian Document Format (ADF) just to format a simple table in a comment.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It takes days to build and constantly requires maintenance.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Smart Way: Webhook Integration
&lt;/h2&gt;

&lt;p&gt;Instead of building a custom integration from scratch, you can use a native Atlassian Forge app that does the heavy lifting for you.&lt;/p&gt;

&lt;p&gt;My team at Orbit A recently released the Playwright Results for Jira &amp;gt;&amp;gt;&amp;gt; &lt;a href="https://marketplace.atlassian.com/apps/1364170176/playwright-results-for-jira?hosting=cloud&amp;amp;tab=overview&amp;amp;showOnlyPublic=true" rel="noopener noreferrer"&gt;Link to Atlassian Marketplace&lt;/a&gt;. It’s a zero-config app that generates a secure Webhook URL for your Jira project. You just send a simple JSON payload to this URL, and it instantly renders beautiful charts and tables right inside the Jira Issue Panel.&lt;/p&gt;

&lt;p&gt;Here is how you can set it up in under 2 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step-by-Step Guide
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Install the App&lt;/strong&gt;&lt;br&gt;
Head over to the Atlassian Marketplace and install the Playwright Integration for Jira (it’s free to try).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Generate Your Webhook&lt;/strong&gt;&lt;br&gt;
Once installed, go to your Jira Apps menu and open the Playwright Configuration page. Click “Generate Webhook”. You will get two things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A Webhook URL.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A secure Token.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fua7ukjm02u0j6nfxuzxo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fua7ukjm02u0j6nfxuzxo.png" alt="config page" width="800" height="829"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Add a Simple POST Request to Your Pipeline&lt;/strong&gt;&lt;br&gt;
You don’t need any complex dependencies. After your Playwright tests finish running (and generate a JSON report), you can use a simple Node script or a curl command to push the data to Jira.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a file named jira-reporter.js in your Playwright project root.&lt;/li&gt;
&lt;li&gt;Paste the code below into it.&lt;/li&gt;
&lt;li&gt;Run tests: JIRA_ISSUE_ID=10001 npx playwright test --reporter=./jira-reporter.js
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const reporterCode = `// playwright-jira-reporter.js
class JiraReporter {
  constructor(options = {}) {
    this.issueId = options.issueId || process.env.JIRA_ISSUE_ID;
  }

  onBegin(config, suite) {
    this.suite = suite;
    this.startTime = Date.now();
  }

  async onEnd(result) {
    const duration = Date.now() - this.startTime;
    const stats = { passed: 0, failed: 0, skipped: 0, duration: duration };
    const tests = [];

    const traverse = (suite) =&amp;gt; {
      for (const test of suite.tests) {
        const outcome = test.results[test.results.length - 1];
        if (!outcome) continue;

        let mappedStatus = 'skipped';
        if (outcome.status === 'passed') {
          stats.passed++;
          mappedStatus = 'passed';
        } else if (outcome.status === 'failed' || outcome.status === 'timedOut' || outcome.status === 'interrupted') {
          stats.failed++;
          mappedStatus = 'failed';
        } else {
          stats.skipped++;
        }

        tests.push({
          title: test.title,
          status: mappedStatus,
          duration: outcome.duration || 0
        });
      }
      for (const child of suite.suites) traverse(child);
    };

    traverse(this.suite);

    const overallStatus = stats.failed &amp;gt; 0 ? 'failed' : 'passed';

    const payload = {
      token: "${token}", // Auto-injected by Jira
      issueId: this.issueId,
      status: overallStatus,
      summary: stats,
      tests: tests
    };

    if (!this.issueId) {
       console.warn('\\n[Jira Reporter] No JIRA_ISSUE_ID provided. Skipping Jira update.');
       return;
    }

    console.log('\\n[Jira Reporter] Sending report to Jira issue:', this.issueId);

    try {
      await fetch('${webhookUrl}', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload)
      });
      console.log('[Jira Reporter] ✅ Successfully sent to Jira!');
    } catch (e) {
      console.error('[Jira Reporter] ❌ Failed to send to Jira:', e);
    }
  }
}

module.exports = JiraReporter;`;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;(Important: Please ensure issueId is the numeric ID, e.g., 10023, not the Key like PROJ-1)&lt;/em&gt;&lt;br&gt;
&lt;strong&gt;How to find the Numeric Issue ID:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the Jira Issue you are testing.&lt;/li&gt;
&lt;li&gt;Look at the URL in your browser.
— If you are on a Board: You will see ...&amp;amp;selectedIssue=10023. The number is the ID.
— If you are in the direct issue view: You can navigate to Jira ticket → click ‘Actions’ button → click ‘Export XML’ → copy value of ‘key_id’, i.e. KAN-7 (here you’ll need to copy 10134)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faf6pkqxaec6i5ulbdum8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faf6pkqxaec6i5ulbdum8.png" alt="issueID example" width="800" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: You can trigger this script in your GitHub Actions, GitLab CI, or Jenkins pipeline dynamically passing the current Jira Issue ID based on the branch name!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Result: No More Context Switching&lt;/strong&gt;&lt;br&gt;
As soon as the pipeline finishes, the developer or PM opening the Jira ticket will see this immediately on the right-side panel:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypteuoh5kiwl424wz3ag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fypteuoh5kiwl424wz3ag.png" alt="main page" width="800" height="463"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;They don’t need to ask for test results history. They can click on the Select Run tab to see 5 latest test runs and their results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsewxrhzwpkiquruxyn0u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsewxrhzwpkiquruxyn0u.png" alt="select run feature" width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
Stop acting as a human bridge between your CI/CD pipelines and Jira. By pushing Playwright results directly into Atlassian, you save time, reduce friction between QA and Development, and make software quality visible to everyone.&lt;/p&gt;

&lt;p&gt;👉 Try Playwright Integration for Jira on the Atlassian Marketplace &amp;gt;&amp;gt;&amp;gt; &lt;a href="https://marketplace.atlassian.com/apps/1364170176/playwright-results-for-jira?hosting=cloud&amp;amp;tab=overview&amp;amp;showOnlyPublic=true" rel="noopener noreferrer"&gt;Here is the Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you found this helpful, follow Orbit A on LinkedIn&lt;/strong&gt; &lt;a href="https://www.linkedin.com/company/orbit-a-apps/" rel="noopener noreferrer"&gt;https://www.linkedin.com/company/orbit-a-apps/&lt;/a&gt; for more tips on bridging the gap between testing and project management. We also have native integrations for Cypress, k6, and JMeter!&lt;/p&gt;

</description>
      <category>playwright</category>
      <category>atlassian</category>
      <category>testing</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
