Level 1 · Lesson 7
Hang the bell
Level 1 · Lesson 7Run code when a dish ticket is created, with nobody looking at a card, and read what it did in the kitchen log.
Behind, or starting here? Download the code as it should be before this lesson.
So far the app only works when someone opens a card. Some work should happen by itself: when a new dish ticket goes up, the kitchen should check the supplier has the recipe. Jira can tell your app about events like that.
Someone creates a work item.
In the kitchen: A new dish ticket goes up.
Atlassian’s own products · House systems
Jira work items Dish tickets
A Jira issue. In this course each work item names one dish, such as “Pad thai”.
A ticket on the board for one dish.
Select any box in the diagram to see what it is.
Step 1: Write what happens when it rings
Locked until the step before it is done.
Runs in the Atlassian cloud · Back of house
Product trigger · the bell
A trigger module runs a function when something happens in the product, such as avi:jira:created:issue when a work item is created. The function gets an event with the details instead of a click, and nobody sees its answer. It is a separate function from the resolver, with its own key and handler.
In the kitchen A bell that rings in back of house whenever a new dish ticket goes up.
Create src/bell.js. It reuses the supplier module, and writes what it finds to the log, because there is no card to show it on:
src/bell.jsA new file: look up the new ticket’s dish and write it to the log.
Added: import { findDish } from './supplier/apiNinjas'; |
Added: |
Added: // Runs when a work item is created (avi:jira:created:issue). |
Added: // No one is looking at a card here, so the result goes to the log. |
Added: export async function run(event) { |
Added: const { key, fields } = event.issue; |
Added: const summary = fields?.summary ?? ''; |
Added: console.log(`Bell: ${key} "${summary}" went up.`); |
Added: try { |
Added: const dish = await findDish(summary, process.env.API_NINJAS_KEY); |
Added: console.log(dish ? `Bell: the supplier has a recipe for ${dish.title}.` : `Bell: no recipe for "${summary}".`); |
Added: } catch (error) { |
Added: console.error('Bell: supplier lookup failed:', error.message); |
Added: } |
Added: } |
Why: Product trigger · forge logs
The event carries the new work item, including its key and summary, so the function does not need to ask Jira for them.
Stuck? I changed code in src/
Next step: next
Step 2: Hang the bell on the licence
Locked until the step before it is done.
avi:jira:created:issue to your trigger’s function. Nobody is looking at a card.The bell rings in back of house. Nobody is at the card.Add two things to the manifest: the trigger, which says which event to listen for and which function to run, and the function itself, which points at the run export in src/bell.js:
manifest.yml- A trigger that fires when a work item is created.
- The function it runs.
render: native |
title: Recipe card |
icon: https://developer.atlassian.com/platform/forge/images/icons/issue-panel-icon.svg |
Added: trigger: |
Added: - key: new-ticket-bell |
Added: function: bell |
Added: events: |
Added: - avi:jira:created:issue |
function: |
- key: resolver |
handler: index.handler |
Added: - key: bell |
Added: handler: bell.run |
resources: |
- key: main |
path: src/frontend/index.jsx |
Why: Product trigger · Function
The scope from lesson 6, read:jira-work, also covers receiving work item events, so this needs no new permission.
Stuck? I changed manifest.yml
Next step: next
Step 3: Deploy the bell
Locked until the step before it is done.
A new module with no new permissions is a minor version: deploy, and the site picks it up by itself.
forge deployStuck? The tunnel is running while I deploy or upgrade · Deploy stops after a permission change
Next step: next
Step 4: Ring it, and read the kitchen log
Locked until the step before it is done.
Lives on your laptop · Home kitchen
forge logs · the kitchen log
forge logs shows what your functions wrote with console.log and console.error, and errors Forge caught, for the development environment by default. Lines can take a minute to arrive. With forge tunnel running, the same lines print in the tunnel’s terminal instead, as they happen.
In the kitchen The log where every station writes what it did and what went wrong.
Create a dish ticket in the Kitchen space, such as Green curry. Wait a minute, then read the log:
forge logs --since 15m$ forge logs --since 15m
INFO Bell: KIT-4 "Green curry" went up.
INFO Bell: the supplier has a recipe for Green Curry.Stuck? I changed code in src/
Next step: next
Compare with yours: download the code after this lesson.
What you built
One app, in one folder: a recipe card on every dish ticket that reads the ticket as the person looking at it, buys the recipe from an outside supplier with a key nobody can see, and a bell that checks every new ticket by itself. Level 2 opens a back kitchen in the same app.
Check what you know
Eight questions on Level 1. Each answer explains itself.
Question 1 of 8
Where does
src/resolvers/index.jsrun?Question 2 of 8
The card calls
invoke('getDish'). What has to exist for that to work?Question 3 of 8
Where does the API Ninjas key live?
Question 4 of 8
You added
api.api-ninjas.comto the manifest and ranforge deploy. It stops. What now?Question 5 of 8
With
forge tunnelrunning, you change the manifest. When does Jira see the change?Question 6 of 8
How does
getDishknow which work item the card is on?Question 7 of 8
readSummarycallsapi.asUser().requestJira(…). Which scope does the app need?Question 8 of 8
Who sees what the bell’s function returns?