---
layout: markdown_page
title: "105 - Label Hygiene - Keeping your issues squeaky clean"
---
## Objective:
When you use labels to manage day to day work and define a specific process, often there are situations and times where it's hard to keep labels in the right status. For example:
* **Scenario 1:** Consider a situation where there is a process defined by an overall label (ABC) and the specific steps in the process are defined by the scoped labels (ABC::1, ABC::2, and ABC::3)
- The process assumes that everyone in the team will assign "ABC" and one of the scoped labels "ABC::x"
- However it's likely that people will forget to assign both labels, and over time there will be a mixture of issues missing one of the two labels.
* **Scenario 2:** Consider a process, where you want to summarize issues based on a set of detailed labels that might be assigned to them. Such as, a process where there are 10 scoped labels "ZYX::1, ZYX::2, ZYX::3, ... ZYX::10", and you want to summarize them in to "ODD" and "EVEN". So ZYX::2,4,6,8,10 all would be labeled "EVEN" and ZYX::1,3,5,7,9 would be labeled "ODD".
- You could request your team to update their issues with the right "ODD"/"EVEN" labels based on the ZYX::nnn label
- You could bulk update labels (find all the ZYX::1 issues and then add the "ODD" label, and repeat 9 more times)
In either case, the ODD/EVEN summary labels would be most likely incorrect, as people would forget to update them, or if something changed, they would be wrong
## Solution - Label Hygiene / Triage Bot
Define a set of rules that will automatically
- Add a label when it is missing
- Change or remove a label when it's wrong
- Add a comment, mention a user, and more through comments and /quick actions.
The [Triage Bot](https://gitlab.com/gitlab-org/gitlab-triage) is an Open GitLab project that makes it possible to automate many issue and merge request hygiene tasks to ensure that your projects are more consistently following a given process.
### Example Triage Policies/rules
Here are two examples of how Triage Polices/Rules can automate updates and issue hygiene:
1. This example finds issues that are more than 5 days old, but have no label associated with them, then it adds a comment to ask the Author to do something. The policy also notifies a team member to make them aware of the issue.
```yml
- name: My policy
conditions:
date:
attribute: updated_at
condition: older_than
interval_type: days
interval: 5
state: opened
labels:
- No Label
limits:
most_recent: 50
actions:
labels:
- needs attention
mention:
- markglenfletcher
comment: |
{{author}} This issue is unlabelled after 5 days. It needs attention. Please take care of this before the end of #{2.days.from_now.strftime('%Y-%m-%d')}
```
2. In Strategic marketing, here is a rule that finds any Strategic marketing Requests that are missing a Scoped Workflow label.
```yml
- name: sm_request (MISSING a scoped label and assign it as a New Reqeust)
conditions:
labels:
- sm_request
state: opened
forbidden_labels:
- sm_req::triage
- sm_req::transfered
- sm_req::new_request
- sm_req::declined
- sm_req::completed
- sm_req::backlog
- sm_req::assigned
actions:
labels:
- sm_req::new_request
comment: |
SM TriageBot helping out here: This SM Request issue was not in the workflow, automatically adding it as a new request.
```
### Setting Up the Triage Bot:
There are only two simple steps to set up the TriageBot.
1. Configuring your CI/CD pipeline
2. Drafting your first Triage Policy
3. Setting up a CI/CD Schedule to run your Triage Policies periodically.
#### Step 1: Configuring your CI/CD Pipeline for the first time.
1. The triage bot runs as a scheduled CI pipeline job, so your project will need to define a `gitlab-ci.yml` file. The `gitlab-ci.yml` file is stored in the root directory of your project.
Here is an example of the Strategic Marketing pipeline, where there are three Jobs defined. There are two **Manual** jobs, and one **Scheduled** Job. The two **Manual** jobs either test(`dry-run`) the rules/policies, or actually apply the rules/policies (`policy:run`). The one **Scheduled** job (`schedule:policyrun`), when runs will actually apply the rules/policies.
```yml
>image: ruby:2.4
stages:
- triage
- run
dry-run:triage:
stage: triage
script:
- gem install gitlab-triage
- gitlab-triage --help
- gitlab-triage --dry-run --token $API_TOKEN --source projects --source-id $CI_PROJECT_PATH
when: manual
except:
- schedules
policy:run:
stage: run
script:
- gem install gitlab-triage
- gitlab-triage --token $API_TOKEN --source projects --source-id $CI_PROJECT_PATH
when: manual
except:
- schedules
schedule:policyrun:
stage: run
script:
- gem install gitlab-triage
- gitlab-triage --token $API_TOKEN --source projects --source-id $CI_PROJECT_PATH
only:
- schedules
```
2. The TriageBot needs to have access and permission to your GitLab project to read and update issues. This is called a "token", and is stored in GitLab using a "CI/CD Variable" - in this case it is the `$API_TOKEN` that you see in the above example pipeline.
You will need to configure a [GitLab CI/CD Environment Variable](https://docs.gitlab.com/ee/ci/variables/)`$API_TOKEN` for these jobs to run.
Here's how:
| **2. Setting Up CI-CD API Token Variable** | Image |
|------|-----|
| 1. In your project select the left menu option `Settings-->CI/CD` | {: .margin-right20 .margin-left20 .margin-top20 .margin-bottom20 .image-width30pct } |
| 2. Then expand the `Variables` section | {: .margin-right20 .margin-left20 .margin-top20 .margin-bottom20 .image-width80pct } |
|3. Add a new line where
- Type= "Variable"
- Key = "API_TOKEN"
- Value = Your API Key. - You have an **API Key** don't you? (See short instructions below)
- Set Masked to True. |{: .margin-right20 .margin-left20 .margin-top20 .margin-bottom20 .image-width80pct } |
| 4. Save Variables | |
| **3. Getting your API Key** | Image |
|------|-----|
| 1. The API Key is linked to your account and basically gives the Bot permission to act on your behalf. First click on the dropdown on your personal settings in Gitlab. | {: .margin-right20 .margin-left20 .margin-top20 .margin-bottom20 .image-width50pct } |
| 2. Select `Access Tokens` and
- Give the access token a Name
- Leave the Expiration Date blank (unless you want it to expire)
- Select "API" for the **Scopes**
- Click **Create personal access token** |  |
| 3. The Personal Access Token will appear at the top of the page. |  |
| 4. Copy the Token and then Add it to the **API_TOKEN Value** in the CI/CD Variables settings. | |
#### Step 2: Setting up your FIRST Triage policy
The Triage Policies/Rules are defined in a `YML` file called `.triage-policies.yml` which is stored in the root directory of your project. For **DETAILED** instructions about rules and policy options read the [Defining a Policy](https://gitlab.com/gitlab-org/gitlab-triage#defining-a-policy) section in the README.md file in the [Triage Bot](https://gitlab.com/gitlab-org/gitlab-triage) project.
1. Create a new file in the root directory called `.triage-policies.yml`
1. Paste in the following first simple rule:
```yml
resource_rules:
issues:
rules:
- name: find all open issues - any label (simple - should be lots)
conditions:
state: opened
```
3. Commit and merge your changes.
This will trigger a pipeline, where the Jobs should all be skipped. You should see this at the bottom of your screen.
{: .margin-right20 .margin-left20 .margin-top20 .margin-bottom20 .image-width80pct }
| **4. Dry-Run TriageBot** | Image |
|------|-----|
| 1. Click on the Pipeline link and go to the pipeline screen |{: .margin-right20 .margin-left20 .margin-top20 .margin-bottom20 .image-width80pct } |
| 2. Run the "Dry Run" pipeline job. |{: .margin-right20 .margin-left20 .margin-top20 .margin-bottom20 .image-width80pct } |
| 3. Click on the job and watch it run. | {: .margin-right20 .margin-left20 .margin-top20 .margin-bottom20 .image-width80pct } |
| 4. Fist it starts by creating a container and getting a runner growing (That means your CI job is defined OK so far) | {: .margin-right20 .margin-left20 .margin-top20 .margin-bottom20 .image-width80pct } |
| 5. Then it prompts the Triage bot to show it's help output (that means it's working, and your API key is good) | {: .margin-right20 .margin-left20 .margin-top20 .margin-bottom20 .image-width80pct } |
| 6. Then the job runs the "Dry-Run" and you see the output from the bot as it runs. Just one job - find all the open issues, so it runs fast, finds over 1,000 issues. Since the policy/rule had no filters or actions, the job finishes. | {: .margin-right20 .margin-left20 .margin-top20 .margin-bottom20 .image-width80pct } |
Now, you need to define any specific policies/rules that you need for your project.
### Step 3: Scheduling Jobs
| **Scheduling Jobs** | Image |
|------|-----|
| 1. Go to CI/CD-->Pipelines on the left menu | {: .margin-right20 .margin-left20 .margin-top20 .margin-bottom20 .image-width20pct } |
| 2. Click on Create New Schedule | {: .margin-right20 .margin-left20 .margin-top20 .margin-bottom20 .image-width80pct } |
| 3. Create the schedule
- Write a Name/description
- Select an Interval pattern (how frequently do you want it to run. Probably daily.)
- Leave the `Target Branch`, and `Variables` options with the default
- Click on Save Pipeline Schedule. | {: .margin-right20 .margin-left20 .margin-top20 .margin-bottom20 .image-width80pct } |
#### Success and Next Steps.
From here, you can build/draft your specific policies/rules for your project.