Fix quality gate silently passing when historyPath is set (fixes #895) - #924
Open
d-braun wants to merge 1 commit into
Open
Fix quality gate silently passing when historyPath is set (fixes #895)#924d-braun wants to merge 1 commit into
d-braun wants to merge 1 commit into
Conversation
d-braun
force-pushed
the
fix/895-quality-gate-history-deadlock
branch
from
September 3, 2026 11:50
69929d8 to
688a816
Compare
d-braun
force-pushed
the
fix/895-quality-gate-history-deadlock
branch
from
September 4, 2026 17:26
688a816 to
a372d01
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
Fixes #895.
When
historyPathis configured,allure quality-gateexits with code 0 and prints nothing, no matter how many rules the results violate. The only trace it leaves is anallure-report/directory containing a singletest-results.jsonand noquality-gate.json, exactly as reported in the issue.allure generateandallure runhit the same defect; there it goes mostly unnoticed because the report has already been written by the time the process stalls.Root cause.
AllureLocalHistoryopens streams on aFileHandlewithautoClose: falseand then awaitsFileHandle.close()in afinallyblock without ever destroying them. Such streams are never destroyed on their own, and the handle stays referenced until they emit"close"— soFileHandle.close()waits for a reference that is never released and never settles. As a consequenceAllureReport.done()never returns, the event loop drains, and Node exits with code 0 before the quality gate is ever validated.This is why the issue looks like the config file is ignored: the reporter's config sets
historyPath, while the--max-failuresrun they compared against was made without--configand therefore without history. Rule parsing was never the problem.Note that running the CLI through
yarn allure …hides the defect — Yarn PnP preloads.pnp.cjs, which shifts the timing enough forclose()to settle. Under plainnode/npx, which is what users run, it deadlocks. Vitest masks it as well. The numbers below come from a cleannpm i allure@3.16.0with the builthistory.jsswapped in and run under plainnode:quality-gatewithhistoryPathquality-gate.jsonhistoryLimitgeneratewithhistoryPathdone()never returnedChanges.
packages/core/src/history.ts— destroy every stream opened on the history file handle before closing it, in the order the streams were opened: destroying a reader that shares its handle with a still open writer never completes, whereas destroying the writer closes the reader along with it. Closing the handle toleratesEBADF, because a destroyed stream may already have closed the descriptor depending on the runtime.packages/cli/src/commands/qualityGate.ts— safety net: a quality gate must never pass silently. If the process is about to exit before the validation has finished, the command now reports it and exits with code 1 instead of leaving the caller with a successful exit code. Checked against the unfixed deadlock, it turns the silent exit 0 into a loud failure.Tests.
packages/core/test/history.streams.test.ts(new) — asserts that every stream opened on the history file handle is closed, for the new-file, existing-file and read paths. All three fail without the fix.packages/cli/test/commands/qualityGate.test.ts— two tests for the new safety net: it fires on an interrupted run and stays silent on a completed one.yarn format:check, oxlint and the@allurereport/core(528) andallure(217) suites pass.Checklist