skip to content

For a failure that recurs every run, would you attach the tracker link to each occurrence in a results server such as ReportPortal, or write a standing rule in Allure 3's `resolutions` config?

level: principalimportance: nice to knowfreq 29%

answer

  1. where the decision lives, and who reviews it
  2. one row versus one matcher
  3. provenance against reviewability
  4. blast radius invisible until it over-matches
  5. neither placement expires on its own

basics

~20 s

Attaching per occurrence keeps a record of who linked what and when, but needs a person or a machine match each time. A standing rule applies from the first run and gets code review, but its blast radius is invisible.

solid answer

~50 s

The choice is really about where the decision is recorded and who reviews it changing. A per-occurrence link in ReportPortal is a row carrying `ticketId`, `btsUrl`, `btsProject`, `url`, `pluginName` and a `submitDate`, attached to one failure - excellent provenance for an individual decision, but it needs an act for every new occurrence and it lives in a database nobody diffs. A standing rule under `resolutions` in `allurerc` matches by `messageRegexp`, `testCaseId`, `retryHash` or `environment` and applies from the first run with no human and no server - reviewable in a pull request, but with a reach that stays invisible until it over-matches. My rule of thumb: one incident belongs on the occurrence, a recurring known cause belongs in the config, and anything that suppresses rather than annotates belongs in the config regardless, because suppression is policy.

go deeper

for a junior

Recall that a tracker tie can either be attached to one occurrence in the results server or expressed as a rule in the report's own configuration, and that only the second applies automatically to future runs.

for a middle

Compare the two concretely: a stored link carries a submitDate and covers exactly one failure, while a rule matches by pattern or id and covers whatever it happens to catch, on every run.

for a senior

Argue the operational cost of each - re-linking by hand indefinitely on one side, a matcher silently widening on the other - and show where a written baseline gives you evidence of what actually happened.

for a principal

Own the accountability question: which decisions must be reviewed by more than one person, what a suppression comment must contain, and who is responsible for taking a tie down once it is no longer true.

## The two placements The same tie between a recurring failure and a tracker item can live in two very different places, and the choice is not really about tooling. It is about where a decision is recorded and who gets to see it change. **Per occurrence, in the results server.** In ReportPortal, someone - or an automatic reuse of an earlier verdict - attaches an `ExternalSystemIssue` to that failure's issue. The link is a row: it carries `ticketId`, `btsUrl`, `btsProject`, `url`, `pluginName` and a `submitDate`, and it is attached to this occurrence of this failure. **As a standing rule, in the report configuration.** In Allure 3, a rule under `resolutions` in `allurerc` matches failures by `messageRegexp`, `testCaseId`, `retryHash` or `environment`, and attaches an `issue` id - or suppresses the failure as `muted` or `accepted` - every run, with no human in the loop at all. ## What each one buys | | per-occurrence link | standing rule | |---|---|---| | where it lives | the results server's database | a file in the repository | | who reviews a change | whoever was watching the screen | whoever reviews the pull request | | applies to | the occurrence it was attached to | every future run that matches | | carries provenance | `submitDate` on each link | the commit history of the config file | | blast radius | exactly one failure | whatever the matcher happens to catch | | works with no server | no | yes | The per-occurrence link's real virtue is **auditability of the individual decision**. Every link says when it was attached, and it is attached to one thing. If you want to know what somebody actually believed about a specific red run, that record exists. Its cost is that it needs an act - a person, or a machine reuse of an earlier verdict - for each new occurrence, and it lives in a database nobody diffs. Six months of accumulated links are invisible to code review. The standing rule's real virtue is **reviewability of the policy**. It is text in the repository, so adding a suppression is a diff somebody approves, and removing one is a diff too. It applies from the very first run on a fresh workspace, needing no server and no human. Its cost is the mirror image: a matcher's reach is invisible until it over-reaches. `messageRegexp` searches rather than matching the whole message, so a rule written for one failure quietly absorbs later failures whose messages merely contain the phrase - and if it is `muted` or `accepted`, those new failures never reach the gate. ## The third shape, which is easy to miss There is a middle option that neither of the above is: a **written baseline**. Allure 3's `known-issues.json`, produced at `knownIssuesPath` or the path given to `--known-issues`, is not a rule and not a per-occurrence link. It is the run's own record of which failures were resolved as `issue` and under which issue id, keyed by retry hash. It decides nothing, but it is diffable, and a diff is the only mechanical way to see a ticket silently acquiring failures it was never about. If you adopt standing rules, adopt the baseline with them; the rules are the policy and the baseline is the evidence of what the policy actually did. ## How I would decide The axis I would use is **how often the answer changes and who is qualified to change it**: 1. **A failure that is genuinely one incident** - a specific case waiting on a specific fix - belongs on the occurrence. It is a fact about that run, and encoding it as a rule creates a matcher that outlives the fact. 2. **A failure that recurs across many cases and many runs from one known cause** - a broken shared dependency, an environment that is legitimately unhealthy - belongs in the config, because the alternative is re-attaching the same link by hand indefinitely. 3. **Anything that suppresses rather than annotates** belongs in the config regardless, because suppression is a policy decision and policy decisions should be reviewed by more than one person. In Allure 3 that is `muted` or `accepted`, and both require a `comment` - so make the comment carry an owner and a review date. 4. **Never both for the same failure.** Two mechanisms attaching the same ticket produce two records that drift, and the drift is undetectable by inspection. ## The trap in both Whichever you choose, neither placement expires. A link has no status field and a rule has no expiry. So the placement decision must come with a companion decision about *review*: a scheduled sweep that asks the tracker whether these ticket keys are still open, and a convention that an undated suppression fails review. Choosing where the tie lives is the easy half; choosing who is accountable for taking it down is the half that actually decides whether the mechanism helps or rots.

  • Where does Allure 3's `known-issues.json` fit into that choice?
    It is neither placement - it is the run's own written record of which failures were resolved as `issue` and under which issue id, written at `knownIssuesPath` or the path given to `--known-issues`. It decides nothing, but it is diffable, and a diff between runs is the only mechanical way to see a ticket quietly acquiring failures it was never about.
  • Why not use both mechanisms for the same failure?
    Because two records of the same tie drift, and the drift is undetectable by inspection. Someone removes the config rule believing the failure is unlinked, while the server still shows a link attached months ago - or the reverse. Pick one home per failure and make the other one's absence deliberate.

saying these in an interview costs you the question

  • Treating this as a tool comparison rather than a review question
  • Assuming a standing rule's reach is obvious from reading it
  • Believing a per-occurrence link is visible to code review
  • Putting a suppression where only one person ever sees it
  • Expecting either placement to expire on its own