Skip to content

fix: Hibernating filter in Devtron Apps list shows incomplete results (pager #2974) - #7049

Merged
Shivam-nagar23 merged 1 commit into
mainfrom
fix/hibernating-filter-pagination-2974
Sep 22, 2026
Merged

Shivam-nagar23 merged 1 commit into
mainfrom
fix/hibernating-filter-pagination-2974

Conversation

@Shivam-nagar23

@Shivam-nagar23 Shivam-nagar23 commented Sep 22, 2026 •

Copy link
Copy Markdown
Member

Description

Fixes https://github.com/devtron-labs/sprint-tasks/issues/2974

The Devtron Apps list, filtered by App Status → Hibernating, returned only a handful of applications and reported that handful as the total, so no further pages were offered — while the CSV export of the same data showed many more hibernating applications.

Root cause

AppListingServiceImpl.FetchAppsByEnvironmentV2 special-cased the HIBERNATING filter. Whenever HIBERNATING was among the selected statuses, the entire AppStatuses list was blanked before the repository filter was built:

if isFilteredOnHibernatingStatus {
    appStatusesFilter = fetchAppListingRequest.AppStatuses
    fetchAppListingRequest.AppStatuses = []string{}   // whole status filter dropped
}

So the SQL that actually ran carried no status predicate at all:

  • page query — SELECT DISTINCT a.id ... WHERE a.active AND a.app_type = 0 <other filters> LIMIT ? OFFSET ?
  • count query — count(distinct a.id) over that same status-less WHERE

The status filter was then re-applied in memory, after pagination, to the single page that came back, and the total count was overwritten with the size of the surviving slice:

envContainers = filteredContainers
appSize = len(filteredContainers)

Hence the filter only ever saw the hibernating apps that happened to land on the requested page of the unfiltered listing.

Why the filter belongs in SQL

The premise of the workaround — "AppStatus is available in Db for only ArgoApps" — does not hold for HIBERNATING:

  1. It is persisted in app_status.status. appStatus.UpdateStatusWithAppIdEnvId normalises Suspended/Hibernated to "HIBERNATING" on write; AppService.ComputeAppstatus → GetHibernationStatus writes it for GitOps pipelines. Present since Jun 2024 — ten months before this workaround was added in Apr 2025.
  2. The in-memory pass read the very same column it skipped. container.AppStatus comes from aps.status as app_status in GetQueryForAppEnvContainers. The in-memory comparison and the SQL predicate aps.status IN (?) match identical data — the only difference is that one runs before LIMIT/OFFSET and the other after. Per-row semantics are therefore unchanged by this PR; only which rows and what count reach the client.
  3. The on-the-fly enrichment the workaround protected no longer runs in this path. updateAppStatusForHelmTypePipelines is commented out in FetchAppsByEnvironmentV2 (removed for slowness), is a return nil stub in OSS, and is additionally gated behind FETCH_HELM_PIPELINE_APP_STATUS (default false).

The change

Pure deletion — 11 insertions, 31 deletions in one file. buildAppListingWhereCondition already emits and aps.status IN (?) for any status list, and already handles the NOT DEPLOYED combination, so nothing replaces the removed code:

  • removed the block that blanked fetchAppListingRequest.AppStatuses
  • removed the post-pagination in-memory filter and the appSize = len(filteredContainers) override
  • removed the now-unused isFilteredOnHibernatingStatus helper and its import
  • added a TODO (helm pipelines) note in place of the removed comment

No migration, no config change, no API contract change.

Also fixed, as collateral

Combination filters were broken by the same blanking:

  • Healthy + Hibernating — blanked both predicates, so Healthy also lost its SQL filter.
  • Hibernating + Not Deployed — additionally killed the NOT DEPLOYED SQL branch, and "NOT DEPLOYED" is never a stored aps.status, so the in-memory pass silently dropped every not-deployed app.

The reported count also changed units: SQL returns count(distinct a.id) (apps) while len(filteredContainers) counted app-env rows, so an app hibernating in two environments contributed 2.

Known gap — deliberately not addressed here

Helm-type (non-GitOps) CD pipelines never get an app_status row, so a hibernated helm-pipeline app cannot be matched by this filter. This is pre-existing, not a regression: the in-memory pass read the same empty column, so those apps matched neither before nor after. Measured on the reporting environment, this cohort is a small fraction of hibernated app-environments; the overwhelming majority are GitOps pipelines and are covered by this fix.

The correct fix is to persist helm-pipeline status into app_status from the status-sync worker — after which the SQL predicate covers them for free — rather than fanning out live status calls during a list request, which is what updateAppStatusForHelmTypePipelines did and why it was removed from this path. Recorded as a TODO in the code; needs a separate ticket.

Related PRs

All four carry the identical change. devtron and devtron-enterprise are a hard fork at the same module path, and the fix is needed on both main and hotfix-v0.46.0, so merging only some of these leaves the rest broken:

Repo Base PR
devtron-enterprise main devtron-labs/devtron-enterprise#3420
devtron-enterprise hotfix-v0.46.0 devtron-labs/devtron-enterprise#3421
devtron (OSS) main #7049
devtron (OSS) hotfix-v0.46.0 #7050

Supersedes the earlier agent-authored drafts devtron-labs/devtron-enterprise#3418 and #7048, which took a different approach (an unpaginated fetch capped at 100k rows plus live per-pipeline status calls). Those are closed.

How Has This Been Tested?

go build ./pkg/app/... ./internal/sql/repository/... ./api/restHandler/app/appList/... passes on the enterprise hotfix-v0.46.0 branch. No runtime test has been run — there is no existing test harness around FetchAppsByEnvironmentV2. Correctness rests on the code trace and on querying app_status directly in the affected environment, so please treat the QA list as required rather than optional.

  • Apply Devtron Apps → Filter → App Status → Hibernating in an environment with many hibernating apps. All should be listed, paginated, with an accurate total count.
  • Cross-check the total against:
    sql SELECT count(DISTINCT a.id) FROM app a LEFT JOIN pipeline p ON a.id = p.app_id AND p.deleted = false LEFT JOIN app_status aps ON aps.app_id = a.id AND p.environment_id = aps.env_id WHERE a.active = true AND a.app_type = 0 AND aps.status IN ('HIBERNATING');
  • Page through to the last page — no duplicates, no gaps.
  • Regression: Healthy / Degraded / Progressing / Missing filters individually.
  • Regression: Healthy + Hibernating and Hibernating + Not Deployed — both should return the union, correctly counted.
  • Regression: Hibernating combined with project, environment, cluster/namespace, tag and app-name-search filters.
  • Regression: both sort modes (appNameSort, lastDeployed), ascending and descending.
  • Regression: as a non-super-admin with access to a subset of apps, the count reflects only permitted apps.
  • Compare the UI list against the CSV export — they should now agree.

Checklist:

  • The title of the PR states what changed and the related issues number (used for the release note).
  • Does this PR requires documentation updates? — No.
  • I've updated documentation as required by this PR.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have tested it for all user roles. — pending QA (see RBAC item above).
  • I have added all the required unit/api test cases. — not added; no existing harness for this service method.

Does this PR introduce a user-facing change?

Fixed: the Hibernating filter in the Devtron Apps list now returns every hibernating application, with correct pagination and an accurate total count. Previously the status filter was applied after pagination, so only the hibernating apps that fell on the requested page of the unfiltered list were shown, and that number was reported as the total. Also fixes the Healthy + Hibernating and Hibernating + Not Deployed filter combinations.

🤖 Generated with Claude Code

…nation

The Devtron Apps list dropped the entire AppStatuses filter whenever
HIBERNATING was among the selected statuses, ran LIMIT/OFFSET and
count(distinct a.id) over the *unfiltered* app set, and only then re-applied
the status filter in memory -- to the single page that came back -- while
overwriting the total count with the size of that surviving slice.

So the filter returned just the hibernating apps that happened to land on the
requested page of the unfiltered listing, and reported that handful as the
grand total, leaving the UI with no further pages. Verified against a customer
database: 592 hibernating apps exist, 2 were shown.

HIBERNATING is an ordinary value persisted in app_status.status
(appStatus.UpdateStatusWithAppIdEnvId normalises Suspended/Hibernated to it),
and the in-memory pass compared against that very same column -- so the
predicate was always expressible in SQL. buildAppListingWhereCondition already
emits `aps.status IN (?)` for any status list, including the NOT DEPLOYED
combination, so the workaround is simply removed rather than replaced.

This also fixes combination filters that were collateral damage: selecting
Healthy + Hibernating blanked both predicates, and Hibernating + Not Deployed
additionally killed the NOT DEPLOYED SQL branch.

The workaround was originally added for Helm-type pipelines, whose status is
not persisted in app_status. That cohort is unaffected either way -- the
in-memory pass read the same empty column -- and is now documented as a TODO
in place of the removed code.

Pager: devtron-labs/sprint-tasks#2974

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Some linked issues are invalid. Please update the issue links:\nIssue # in is not found or invalid (HTTP }404).\n

@github-actions

Copy link
Copy Markdown

Some linked issues are invalid. Please update the issue links:\nIssue # in is not found or invalid (HTTP }404).\n

1 similar comment
@github-actions

Copy link
Copy Markdown

Some linked issues are invalid. Please update the issue links:\nIssue # in is not found or invalid (HTTP }404).\n

@sonarqubecloud

Copy link
Copy Markdown

@Shivam-nagar23
Shivam-nagar23 merged commit 6ab8595 into main Sep 22, 2026
15 of 18 checks passed
@Shivam-nagar23
Shivam-nagar23 deleted the fix/hibernating-filter-pagination-2974 branch September 22, 2026 09:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants