Releases and automatic moves
Versions, environments, and rules that move an issue when a merge request is opened, a pipeline deploys or a release ships.
What it is made of
An issue can move by itself: to review when its merge request is opened, to «on staging» when a pipeline puts it there, to closed when the release it went out in ships. Nobody has to remember to drag the card, and the board says where the work really is.
- A workflow with a state for each step — the ready-made «Releases by environment», or your own.
- Rules: an event, the state the issue must be in, and the state it moves to.
- The repository’s webhook, so the tracker hears of a branch and a merge request when they happen.
- One request from your pipeline saying what went out, and where.
- Versions — the releases an issue goes out in.
Each part works without the others. Everything on this page is set up by the project’s lead, from the board’s ⋯ menu.
The ready-made workflow
- Open the board, then ⋯ → States & transitions…
- Press Use another… and choose Releases by environment.
- If the project already has issues, say for each state they stand in which new state they go to.
- Press Use Releases by environment.
| State | What it means |
|---|---|
| To Do | Not started. |
| In Progress | Somebody is working on it. |
| Code Review | A merge request is open. |
| Ready for testing | Merged; waiting for a tester. |
| Testing / QA | Being tested. |
| Ready for Staging | Passed; waiting for the next deployment to staging. |
| Deployed to Staging | On staging, not yet checked there. |
| Ready for Prod | Checked on staging; waiting for the next deployment to production. |
| Deployed to Production | Out, and not yet said to be right there. Not a finished state. |
| Closed | Finished. |
| Cancelled | Will not be done. Also a finished state. |
| Blocked | Waiting on something. Reachable from every unfinished state, and leads back to each. |
Closed and Cancelled can be reached from every unfinished state, so work that goes out to no environment — a chore, an investigation — is closed from where it stands. The moves have names of their own («Deploy to Staging», «Preprod verified»), and a tool reads those names in transitions[].name.
With the workflow come three environments — dev, staging, prod — where the project had none, a board column per state where the board had no columns of its own, and seven rules, switched off. The workflow becomes the project’s own: edit it afterwards like any other.
The rules come switched off on purpose. Until you switch one on, nothing moves by itself — see the next section.
Rules that move issues
⋯ → Rules… lists the project’s rules. The seven that come with the workflow:
| When | From | To | Needs |
|---|---|---|---|
| A branch naming the issue is made | To Do | In Progress | the webhook |
| A sub-task of the issue is started | To Do | In Progress | — |
| A merge request naming it is opened | In Progress | Code Review | the webhook |
| A merge request naming it is merged | Code Review | Ready for testing | the webhook |
| A deployment to staging carries it | Ready for Staging | Deployed to Staging | the pipeline’s request |
| A deployment to production carries it | Ready for Prod | Deployed to Production | the pipeline’s request |
| A version it is in is released | Deployed to Production | Closed | a version |
Switch on the ones your project has the plumbing for. You can also write your own: any of these events, plus «all its sub-tasks are finished» and «the issue entered a state»; a merge-request rule can be narrowed to the branch it is merged into, a deployment rule to one environment.
- A rule moves an issue as whoever switched it on. The issue’s history says «the rule “…” (for Anna)». If that person leaves the project, the rule switches itself off rather than run on nobody’s access.
- It is an ordinary move. The workflow’s conditions apply. If the workflow does not allow the move, nothing happens to the issue, and the rule’s journal says why.
- «From» is checked every time. An issue that is not in the state the rule names is left alone — a merge request opened on an issue already in testing does not drag it back.
- Every pass counts. An issue sent back and brought round again is moved by the same rules the second time.
- A rule’s move can fire the next rule, three moves deep at most.
The three moves between them stay with a person, because each is a judgement: «I am testing it», «it passed», «staging is fine».
The repository’s webhook
The repository has to be connected first: ⋯ → Repositories… (GitLab or GitHub).
- In Repositories…, press Set up webhook on the repository.
- Press Generate and copy the Address and the Secret — the secret is stored sealed and never shown again.
- In GitLab: Settings → Webhooks → Add new webhook. Paste the address as the URL and the secret as the Secret token; tick Push events and Merge request events.
- In GitHub: Settings → Webhooks → Add webhook. Paste the address as the Payload URL, choose
application/json, paste the secret, and select Pushes and Pull requests. - Save in both places. The sheet then says when the host was last heard and what it said — a test delivery counts.
An issue is named by its key — ABC-12 — in the branch name, the merge request’s title or its description. Only issues of the project the repository is connected to are moved.
| Event | GitLab | GitHub |
|---|---|---|
| Branch made | the first push of a new branch | a push that creates a branch |
| Merge request opened | opened or reopened | pull request opened or reopened |
| Merge request merged | merged | closed with a merge |
| Merge request closed | closed without merging | closed without a merge |
- The same delivery sent twice — a retry, «Resend» — moves an issue once.
- Everything else the host sends (an update, an approval, a tag) is heard and ignored.
- The host’s delivery log shows our answer: 200 with
outcome—taken,duplicate,ignored,wrongRepository,disabled— or 401 when the secret is not this repository’s.
Without a secret a repository accepts nothing. GitHub’s form-encoded content type is refused: choose application/json.
One request from the pipeline
⋯ → Environments… keeps the project’s environments in order — the last one is where finished work ends up — and shows the command below with your project’s address in it. A step in the pipeline runs it after the deployment has succeeded:
deploy_staging:
stage: deploy
script:
- ./deploy.sh staging
- |
curl -fsS -X POST "https://<workspace>.kaiku.tech/api/projects/ABC/deployments" \
-H "Authorization: Bearer $PM_TOKEN" -H "Content-Type: application/json" \
-d "{\"environment\":\"staging\",\"id\":\"$CI_PIPELINE_ID\",\"revision\":\"$CI_COMMIT_SHA\",\"url\":\"$CI_PIPELINE_URL\",\"fromLast\":true}"PM_TOKEN is a masked CI/CD variable holding a token of somebody who may change issues in the project — see Connecting a tool. The example is GitLab CI; any pipeline that can send a request will do.
| Field | What it says |
|---|---|
environment | Required. One of the project’s environments, by name. |
id | The pipeline’s own name for this deployment. Left out, revision stands in. One of the two is required. |
revision | What went out: a commit, a tag. |
url | A link to the pipeline; the issue’s «Lies on» row opens it. |
fromLast | true: read the issue keys off the messages of the commits since the last deployment reported to this environment. |
from, to | The same, with the range named outright. to defaults to revision. |
issues | The issue keys named outright: ["ABC-12", "ABC-15"]. May be combined with a range. |
repository | group/repo, when the project has several connected and the range is in one. |
version | Also puts those issues in this version of the project, by name. |
- Told once. The same
idfor the same environment again answersrepeated: trueand does nothing, so a retried step is safe. - The answer lists
issuesit carried,unknownkeys that are no issue of the project, how many times a rule ran (rulesRan), thefroma range was read from, and — on the last environment —unfinished: the issues that went out and are not in a finished state. - A range needs the repository connected, and reads commit messages: a merge commit names its branch, a squashed one carries the request’s title. If the repository does not answer, the request fails with 502 and nothing is recorded — run the step again.
- With
fromLast, the first report to an environment reads no range: there is nothing before it. It records where the next one starts. - An environment or a version the project does not have is refused with a 400 — never quietly skipped.
Prefer fromLast to your CI’s «previous commit» variable. That variable is the last deployed commit only if every pipeline deploys; one cancelled or failed pipeline, and its issues are never told they went out.
Where an issue lies
- The issue shows Lies on with every environment it has reached; each opens the pipeline that put it there. An issue on
prodstill saysstagingtoo. - Its history gets one line per environment — «deployed to staging» — however many times it is deployed there.
- The board has a Lies on filter.
- An issue on the last environment that is not finished says so on its Lies on row for as long as that is true.
- Over the API the field is
deployedTo, beside the standard ones; in a search it is returned when asked for by name.
Versions
⋯ → Releases… lists the project’s versions with their dates and progress. An issue may be in several — one per staging cut is a common way to use them — and the issue’s Release row sets them.
- Release marks a version released. If it still holds unfinished work, the screen asks first: leave it, or move it to a version that is still ahead.
- Releasing fires the «version released» rule for each issue still in the version. An issue taken out of a release it missed is not moved.
- In a search:
fixVersion = "2.4.0",fixVersion in releasedVersions(),fixVersion in unreleasedVersions(). - Over the API a version is the standard
/rest/api/2/versionresource, and an issue’s are itsfixVersions; an issue takes versions of its own project only. - A pipeline can put issues in a version as it deploys them: the
versionfield above.
Through MCP
| Tools | What they do |
|---|---|
list_versions, create_version, update_version, release_version | A project’s versions. create_issue and update_issue take fixVersions. |
list_environments, set_environments, report_deployment | The environments, and the same report a pipeline sends. |
list_project_rules, create_project_rule, update_project_rule, delete_project_rule, get_project_rule_runs | The rules and their journal. |
get_started | Says whether the project has this set up, and where to begin. |
A webhook you register hears versions too: jira:version_created, jira:version_updated, jira:version_released, jira:version_unreleased, jira:version_deleted.
What is not there
- A rule cannot change the assignee — only move an issue, add a checklist, or hand the issue to an agent.
- A reported deployment cannot be taken back. A wrong report is corrected by the next one to that environment.
- There is no search clause for «lies on»; the board filters its cards.
- A webhook you register is not told about deployments.
- The ready-made workflow is taken on the screen; there is no MCP tool for a project’s workflow.
- A project mirrored from another tracker takes no deployment reports: its issues live there.
Something missing, or not as described here? Write to hello@kaiku.tech