QA Build from a Jira Issue

A QA build turns the code of one Jira issue into images that QA can test. You do not press a build button. The build starts when the issue moves to In QA.

What it does

The Jira app QA Build adds a field and a panel to the issue. CI/CD Manager does the work.

  1. The developer confirms what to build when the issue moves to Ready for QA.

  2. QA checks that choice when the issue moves to In QA.

  3. CI/CD Manager builds the image of each service.

  4. CI/CD Manager sends one QA e-mail and posts one comment on each related ticket.

  5. The panel shows the build as a card and keeps it up to date.

The Jira app holds no business logic. It shows what CI/CD Manager decides. If the Jira app and CI/CD Manager disagree, CI/CD Manager is right.

Screenshots are not included. The labels on this page are the labels that the app shows.

What you need

  • You can see the issue in Jira.

  • You can comment on the issue. You need this to confirm what to build and to press Rebuild.

  • An administrator has installed the Jira app. See For administrators.

  • Your Jira account may need to be allowed to start QA builds. The administrator sets this.

Step 1. The developer moves the issue to Ready for QA

The screen of this move has the field What to build for QA. The field opens with the services and branches that CI/CD Manager found.

CI/CD Manager looks for them in the branches and pull requests that carry the issue key. See How CI/CD Manager finds the branch.

  1. Read the list. Each row is one service with its branch.

  2. Untick a service that QA must not build.

  3. Select Change on a row to pick another branch. Type part of the branch name to narrow the list.

  4. Select + Add a service to add a service that is missing.

  5. Move the issue.

When the choice on the screen is complete, CI/CD Manager confirms it at once. The field shows a status line, for example Confirmed. If you see Partly confirmed, a message under a service tells you why. Pick another branch or untick that service.

The status line also says Confirming your choice in CI/CD Manager… while it works. Wait until it ends before you move the issue.

Nothing is built in this step. CI/CD Manager only records your choice, with your name and the time.

No QA build needed

Some issues need no image. An example is a change that only touches documentation. For these issues, tick No QA build needed.

  • Ticking it unticks every service.

  • Ticking a service unticks it.

  • You cannot choose both. You choose services to build, or you choose no build.

The app ticks No QA build needed for you only in one case. CI/CD Manager found a pull request for the issue, and the pull request is in no repository that CI/CD Manager builds. The field names the repository and the pull request number. You still move the issue yourself, so a person always confirms the choice.

If nothing at all was found, the field offers the choice but does not tick it.

If a change for the issue appears after someone confirmed No QA build needed, the field does not tick the choice again. It lists the new service and asks you to choose.

Step 2. QA moves the issue to In QA

The same field opens again. It shows what the developer confirmed, who confirmed it, and when. QA can change the choice.

The field opens fast. When the developer has already confirmed at least one service, the field does not search GitHub. It reads the developer’s confirmation and the last build of the issue from CI/CD Manager.

QA can do these things:

  • Untick a service.

  • Add a service with + Add a service.

  • Change a branch with Change. The list shows only branches that exist.

  • Select Look for other branches on GitHub to run the full search.

  • Tick No QA build needed to confirm that no build is required.

The link Look for other branches on GitHub appears only when the field skipped the search. It keeps the rows that you already have, with their ticks and branches. It adds the new branches as unticked rows. You decide whether to tick them. If the search fails, the link changes to Try GitHub again.

If a build of this issue is already running or waiting to be announced, the field tells you before you move the issue. The move then starts nothing new.

If the developer ticked No QA build needed or never confirmed anything, the field runs the full search when it opens. This is slower.

The field after the move

On the issue view the field is read-only. It shows one line, for example Confirmed for QA build, No QA build needed or Not confirmed yet. The QA build panel shows who decided and when.

What happens after the move to In QA

The build starts by itself when the issue reaches In QA. Nobody presses anything.

CI/CD Manager starts a build only when the same person confirmed the field on that screen. If you close the screen, nothing is built. A move without the screen starts no build. Examples are a bulk move, Jira Automation and a board drag. CI/CD Manager then posts a comment that says why.

The QA build panel shows a card for the build. The card keeps itself up to date. You do not reload the page.

The card

The header shows the service, the build number and the branch. For a build of several services, each service has its own line. The line below the header says who started the build and when, for example Moved to In QA 21:01 by <name>.

The card shows four steps.

Step Meaning

Started

CI/CD Manager started the build.

Image

The image is built and tagged.

E-mail

The QA e-mail went out.

Comments

The comments on the tickets were posted.

While the build runs, the card says how long it runs, for example Building the image, started 3 min ago. It does not promise a time. Builds can take more than five minutes.

The lozenge in the card header shows the phase.

Lozenge Meaning

Building

At least one service is still building.

Built

The image is ready. The announcement has not started.

Partly built

Some services built and some failed. The announcement has not started.

Announcing

The QA e-mail is going out, or the comments are being posted.

Ready

The build is announced. Every service reached QA.

Partly ready

The build is announced. Some services failed and did not reach QA.

Failed

Nothing reached QA. See When nothing reached QA.

Not sure

The e-mail was started but never reported back. Check the QA mailbox.

Not sent

The announcement gave up. The panel shows a Submit button.

Expired

Nobody announced the build in time. Start a new build.

If a service fails, its row shows the reason, the end of the log and a link to the run. See When a build fails.

Jira flags

While you keep the issue open, Jira shows a flag at three moments.

  • QA build <number> started. This flag disappears by itself.

  • QA build <number> is ready, with the action Create a QA environment. This flag stays until you close it.

  • QA build <number> failed, with the action Open the run. This flag stays until you close it.

If you open an old issue, no flag appears for a build that ended long ago. A flag shows only a change that happened while you watched.

The QA e-mail and the Jira comment

CI/CD Manager announces the build itself. QA does not come back to press anything. The e-mail and the comments are sent only when at least one service reached QA.

The e-mail

There is one e-mail for each build. Web builds and Jira builds use the same template.

  • The subject is DEV-1234: NBI 1.4.7 + UI 2.0.3 when every service built.

  • The subject says so when the result is partial.

  • The body has one card for each built service, with the image URL, tag and digest.

  • The body lists the services that failed, with the reason and the run link.

  • The body lists the tickets that were commented on.

  • The body lists the tickets that were not commented on, with the reason.

  • If a service built, the body has a Create QA environment button.

The e-mail goes to the standing list from the Settings and to the person who started the build. Only addresses that end with friendly-tech.com are used. At most 20 addresses are used.

The e-mail is never sent twice. If CI/CD Manager does not know whether it was sent, the card shows Not sure. Check the QA mailbox. If nothing arrived, send the e-mail by hand from CI/CD Manager.

The Jira comment

CI/CD Manager posts one comment on each allowed ticket. The author is the app QA Build. The comment mentions nobody. The comment has this shape:

QA build for DEV-1234 (submitted by <name>):
<Project> <build number> on <branch> — <outcome> — <run link>
  • The comment lists all builds of the group, not only the builds of that ticket.

  • The comment adds (attempt N) when a service was retried.

  • The comment never contains the log tail. Open the run link to read the log.

The comment goes to the issue and to every ticket named in the commits of the build. The tickets are decided at the moment of the confirmation, with the permissions of the person who confirmed. A ticket that reaches the branch later is not commented. The e-mail names it.

If you may not comment on a ticket, the ticket is skipped with the reason no permission. The panel shows <KEY> not commented, and the e-mail lists the ticket under Not commented. To fix this, ask the owner of that project to comment, or get the Add Comments permission.

A comment can appear a few minutes after the build ends. The app writes to Jira only while Jira talks to it, about every five minutes. The panel says N comments waiting to be posted in this time. It says N comments could not be posted when a comment failed. A failed comment is not a build failure. The e-mail still carries the result.

If the e-mail or the comments fail four times, the card shows Not sent and a Submit button. Select it to announce the build as yourself. Several issues can share one branch. Then the panel of the other issues shows the block Included in other builds. That build comments on your issue too, so nothing is wrong.

Create a QA environment in Jenkins

After a build with at least one image, the panel shows the primary button Create a QA environment in Jenkins. It opens the same Jenkins job that the QA e-mail offers. The Ready flag has the action Create a QA environment.

The button is not shown while the build runs, or when no service built an image.

Rebuild

Rebuild starts another build. Use it when the first build failed, or when the code changed after the first build.

  • It is offered only while the issue is in In QA.

  • It is offered only while no build of this issue is running.

  • It builds from the services that the person last confirmed. If the person confirmed after the last build, those services are used. Otherwise it uses the services of the last build.

  • Before the first build, the same button is called Build.

  • Choose services and branches lets you pick other services for the rebuild.

Rebuild builds every service again. If one service failed, use Retry on the card. Retry redoes only that service in the same build.

When nothing reached QA

Sometimes no service produces an image. Every build fails, or the announcement is blocked.

CI/CD Manager then does this:

  • It sends no QA e-mail.

  • It posts no comment on any ticket.

  • It sends one notice e-mail to the person who started the build. The subject for a Jira build is DEV-1234: QA build 5 failed.

  • It shows the lozenge Failed on the card. The card never shows Ready.

  • It shows the Jira flag QA build <number> failed, with the action Open the run.

The card says: Nothing reached QA, so no QA e-mail was sent and no tickets were commented. Fix the problem, then press Rebuild.

If the problem was only partial, some services reached QA. The e-mail then says so, and the card shows Partly ready.

Web wizard in CI/CD Manager

QA can also start a build from the web wizard of CI/CD Manager. Step 3 offers two choices: From Harbor and Build on Submit.

  • From Harbor uses an image that already exists.

  • Build on Submit builds the image when you press Submit QA Build in the last step.

After Build on Submit, a progress window opens. You can close the window or the tab. The server finishes the work and sends the QA e-mail. If the build fails, you get one notice e-mail and the failure is recorded in the QA history. QA gets nothing.

Troubleshooting

What you see What to check

The field says CI/CD Manager not answering, and the issue cannot move

The text says nothing can be confirmed. Wait one minute, then try again. Check whether CI/CD Manager opens in the browser. Check whether your Jira account must allow the app access once. Ask the CI/CD Manager administrator to read the log for forge invoke.

The field says Could not load what to build

CI/CD Manager answered, but refused. Read the sentence under the title. It names the reason.

A teammate sees nothing in the field or the panel

Check whether the field is on the screen of that move. Check whether the teammate can see the issue. Check whether the teammate must allow the app access once. This was not confirmed as the cause.

The issue reached In QA and no build started

Open the QA build panel. Read the comment of QA Build on the issue. It names the reason. Examples are a field that was not confirmed on the move, and an account that is not allowed to build. Then use Rebuild.

The field is empty and the move is stopped

The field must hold a confirmation. Tick a service, add one, or tick No QA build needed. Wait until the status line says Confirmed.

The field says Nothing is ticked

Tick at least one service, add one, or tick No QA build needed.

The field says No branch or pull request with <KEY> in its name was found

Check the branch name. Add the service by hand and pick its branch. A branch that was pushed a few seconds ago can take up to a minute to appear.

The list of branches misses the new branch

The branches of one repository are read once a minute. Wait and search again.

The In QA field shows fewer services than you expect

The field did not search GitHub. Select Look for other branches on GitHub.

The card says Build already running

Moving the issue starts nothing new. Wait for the build to end. Then use Rebuild if you need a new one.

Rebuild is missing

The issue is not in In QA, or a build is running.

The card shows Failed

Open the failed service in the card. Read the reason and open the run. Fix the cause. Then press Rebuild.

The e-mail did not arrive

The card shows Not sure or Not sent. Check the QA mailbox. Only friendly-tech.com addresses receive the e-mail.

The panel says N comments waiting to be posted

Wait up to five minutes. This is normal after a restart of CI/CD Manager.

The panel says N comments could not be posted

The app cannot see that issue, or the Jira permission is missing. Ask the administrator. The build is not affected.

Calls fail with a 401 error after the app was reinstalled

Update Forge installation ID in the Settings.

Another issue holds the branch

One branch is built for one issue at a time. See One branch, one issue.

How CI/CD Manager finds the branch

The Project stream field (customfield_10489) only narrows the list of projects to search. The branch decides what is built. If the stream is empty or not mapped, all projects are searched.

The Modules field (customfield_10490) is a hint on the screen. It never changes what is built.

CI/CD Manager looks for the branch in this order. The first source that gives an answer wins.

  1. The targets that a developer confirmed.

  2. GitHub search:

    1. The head branch of an open pull request that names the issue key.

    2. The base branch of a merged pull request that names the issue key.

    3. A branch whose name contains the issue key.

  3. The Fixed Build field. This is the last choice. It is only a hint.

CI/CD Manager checks every branch on GitHub, whatever its source. A branch that does not exist is never built.

Nothing writes the Fixed Build field any more. The Fix Selected button of the web wizard is gone. The build number goes to the e-mail and to the ticket comments.

One branch, one issue

A branch is built for one issue at a time. This is the hold.

  • A group takes the hold on each of its branches when the build starts.

  • The hold stays after the build finishes. It stays until someone submits.

  • The hold ends when the group is Done, All builds failed or Abandoned.

  • The hold also ends when nobody submits for 8 hours. Then the group is Abandoned. The clock starts at the last moment that a service finished. A group with a running build is never abandoned.

The hold works between QA builds and release builds. A release build and a QA build cannot use the same branch together.

Message Meaning

This branch is already being built for DEV-XXXX.

Another issue is building this branch.

Built for DEV-XXXX, waiting for its Submit.

Another issue built this branch and nobody pressed Submit.

This branch is being built for release 7.1.1.

A release build is using this branch.

The release build shows the first two messages when a QA group holds the branch.

Build numbers and Retry

A retry is a new build with the next build number. It is not a re-run. The failed attempt may already have pushed an image, so the old number is not reused. Gaps in the numbers are normal. They are not a bug.

The retry replaces the failed service inside the same group. These rules apply:

  • You can retry only before Submit.

  • You can retry only a service in the state Build failed.

  • You cannot retry when the outcome is unknown. Check Harbor and GitHub Actions first, then start a new build.

  • The limit is the configured number of retries for each service, 2 by default. This is the setting Retries per service.

  • A retry takes the hold again. If another issue took the branch, the retry is refused with the messages above.

  • A group where every build failed can be retried only while its hold is still open. After the hold expires the group is Abandoned, and you start a new group.

  • Two quick presses start one retry.

The retried service shows (attempt N) in the e-mail and in the comments.

When a build fails

Open the failed service in the panel. You see three things:

  • the reason of the failure

  • the log tail of the failed step

  • a link, Open the GitHub Actions run

The log tail is shown on the Jira panel and in the web modal. It is never shown in the Jira comment. CI/CD Manager hides secrets that it recognises, such as tokens and passwords. The tail is limited in length. Do not assume that it is clean.

The tag Likely transient, Code error, Configuration error or Unclassified is a hint. CI/CD Manager guesses it from the name of the failed step. The log tail and the link are always shown, so a wrong guess does no harm.

Hint What it means What to do

Likely transient

The failed step looks like infrastructure: checkout, login or push.

Press Retry.

Code error

The failed step builds, compiles, tests or checks the code.

Read the log tail. The developer fixes the code and pushes. Then press Retry.

Configuration error

The workflow, the branch or the version file path is wrong.

Ask the administrator to fix the project. Then press Retry.

Unclassified

CI/CD Manager cannot tell.

Read the log tail and open the run. Retry when you know the cause.

The reasons of failure have their own labels.

Label Meaning

Could not start

GitHub refused to start the workflow. Check that the build workflow exists.

Run not identified

The workflow started, but GitHub did not say which run it made. Nothing was watched.

Run failed

The run ended with an error.

Run timed out

The run did not finish in time. Check whether it still runs.

Image missing

The run finished, but Harbor has no image for this number.

Harbor unreachable

Harbor did not answer.

Version file not updated

The build number could not be committed. Nothing was started.

Tagging failed

The image is built and safe. The tag in Harbor failed. Tell the administrator.

Submit failed

The image is built. The QA build could not be submitted.

E-mail failed

The builds are fine. The e-mail was not sent. Send it by hand.

Outcome unknown, Outcome unknown (restart)

CI/CD Manager does not know whether the step worked. It is never retried by itself, because that could build twice. Check Harbor and GitHub Actions for this build number.

For administrators

Install the Jira app

A site administrator deploys the Forge app. CI does not deploy it. Run these commands in ft-tools/jira-app:

forge login
forge register    # first time only
npm install
forge deploy
forge install

For later versions, run forge deploy && forge install --upgrade. Add -e production to both commands for production. The app asks for four read scopes — read:jira-work, read:jira-user, read:app-user-token, read:app-system-token — and for one write scope, write:jira-work.

The write scope exists for one thing only: the app writes the QA build comments itself, as QA Build, instead of using a shared CI/CD Manager Jira account. Nothing writes a Jira field. Adding it makes a major version, so somebody with site admin rights has to approve the new version and run forge install --upgrade. Until that is done, comments wait in a queue on the server and nothing is lost; the notes on a move to In QA still appear, because that request brings its own token.

The app also keeps a scheduled trigger, qa-token-refresh, which calls CI/CD Manager every five minutes. Its only job is to hand over a fresh token so the server can write a comment for a build that finished while nobody was looking. The first run is about five minutes after a deploy, so a server that has just restarted writes nothing for up to five minutes and then catches up.

After every reinstall the installation ID changes. If calls fail with a 401 error, update Forge installation ID in the Settings.

Put the field on the two screens

The field What to build for QA does the work, so it has to be on the right screens. Do this once.

  1. Add What to build for QA to the screen of the move to Ready for QA, next to Fixed Version.

  2. Add a field required workflow validator on that move. A field configuration is per field, not per move, so this cannot be done there.

  3. Add the same field to the screen of the move to In QA.

  4. Approve the new major version of the app. It asks for the system token and for the trigger.

The app user needs Browse permission on every project that has the move to In QA. The server reads the recorded change with the app’s own token, and without Browse it cannot, so every move would be refused with a comment.

Settings

Open the Settings of CI/CD Manager.

Setting key Settings label Default Meaning

qa.jobHoldTtlHours

Branch hold (hours)

8

Hours without Submit before the group is Abandoned and the branch is released.

qa.maxRetries

Retries per service

2

Retries for one service. The value 0 turns retry off.

qa.maxLiveJobs

Builds in flight

10

QA builds that can run together.

jira.cloudId

Jira Cloud ID

none

The Jira site that the server accepts. Without it every call is refused.

jira.forgeInstallationId

Forge installation ID

none

The installation of the Forge app that the server accepts.

jira.streamFieldId

Project stream field

none

The Jira field ID of Project stream, customfield_10489 in the source.

jira.qaReadyStatus

Status the developer confirms on

Ready for QA

The status whose move screen asks the developer what to build. Change it when the workflow renames the status.

jira.qaInStatus

Status that starts the build

In QA

The status whose arrival starts the QA build. Rebuild works only in this status.

jira.qaTargetsFieldId

What to build for QA field

customfield_11519

The Jira field ID of What to build for QA. The server matches the value of this field in the change Jira recorded, so a wrong ID means no build ever starts.

jira.qaPostComments

Write Jira comments

off

Whether the flow writes any Jira comment at all — the comment on each ticket after a build, and the note when a move to In QA started nothing. Off, nothing is queued and nothing is written; the e-mail is sent either way. Turn it on when the app’s write:jira-work scope has been approved.

jira.qaTriggerAllowAnyUser

Any Jira user may start a QA build

on

If you clear it, only the listed accounts can build, submit and retry.

jira.qaTriggerAccountIds

Allowed Jira account IDs

empty

The accounts that may build when the setting above is off.

email.qaJiraDefaultRecipients

QA Build from Jira, standing list

empty

Addresses that receive the QA e-mail. Only friendly-tech.com addresses are used, at most 20.

The server also needs the environment variable FORGE_APP_ID. Without it the server refuses every Forge call.

Map streams to projects

Each project has a jiraStreams list in data/projects.json. It names the Project stream values that belong to this project. A stream with no mapping makes the search cover all projects. The Projects screen of CI/CD Manager edits this list.

Access

By default every authenticated user of the Jira site can use the feature. This is a recorded decision. See docs/decisions/LOG.md. These checks still run:

  • The server verifies the token of Forge for real.

  • The server checks the Jira site and the installation against the Settings.

  • Every call uses the permissions of the user in Jira. There is no service account fallback.

  • The server records who started, submitted or retried a build.

  • The server limits calls for each user and limits the builds in flight.

  • The field screen and the trigger are separate doors. The field screen needs the user’s token and refuses the app’s own; the trigger needs the app’s own token, refuses a user token, and refuses any token that does not come from the trigger itself.

  • A move starts a build only when the same person confirmed the field on that screen, less than 30 minutes earlier, and the value of that field in the change Jira recorded is the one the server handed out. Anything else — Jira Automation, a bulk move, the REST API, a board drag with no screen, a value left over from a previous round — starts nothing and gets a comment.

  • The server never builds from what the field says. The field holds a pointer to a record on the server, and the record is what is built.

  • The tickets a build may comment on are decided with the user’s own token at the moment they confirm, and that set is frozen. It can only get smaller afterwards, never larger.

  • The app’s own token, the one that writes the comments, is held in memory only. It is never written to disk, never written to a log, and no request can read it back. The server keeps it for 15 minutes and then stops using it.

  • Only the two app modules that are allowed to — the scheduled refresh and the status trigger — can leave that token with the server. A screen or a panel cannot, even though their requests are equally genuine. The same request sent twice is ignored.

  • The server sends that token to exactly one address, the Jira site named in the Settings, and checks the address again immediately before sending. It uses it for two requests only: posting a comment, and reading the assignee of the ticket it is commenting on.

TLS

The ingress of CI/CD Manager now serves a real certificate from Let’s Encrypt. Jira Cloud must reach the server, so the ingress is public.

More

For the design and the code, see SDD for QA build from Jira.