Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

HelmRepository: use conditional HTTP requests (ETag / If-Modified-Since) when fetching index.yaml

Open
#2,113 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
48/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Quiet
Tech stack
go, kubernetes

Research direction

Start in internal/helm/repository/chart_repository.go at CacheIndex and DownloadIndex, then trace the no-op decision in internal/controller/helmrepository_controller.go around lines 464-468. Verify how response validators can be retained per object and how a 304 reaches the existing unchanged path without reading the body. Done means conditional requests are used when validators exist, while repositories without validators retain current behavior.

Written by the indexing model from the issue text.

Description

Problem

For HTTP(S) HelmRepository objects, source-controller downloads the full index.yaml on every reconcile interval, unconditionally: CacheIndexDownloadIndex issues a plain GET, and only after the download completes is the digest compared against the current artifact to decide the reconcile is a no-op (helmrepository_controller.go#L464-L468). There is no If-None-Match / If-Modified-Since anywhere in the fetch path (the only ETag references in the codebase are the S3/GCS test mocks).

Real-world indexes are large (grafana ~2 MB, prometheus-community ~4 MB, bitnami historically >10 MB), and the cost is linear in the number of objects: N HelmRepository objects pointing at the same or different repos re-download N full indexes per interval, forever, even when nothing changed. In multi-tenant setups where each tenant namespace declares its own HelmRepository (cross-namespace refs disabled), N grows with the tenant count.

Measurements

Bench: k3s + source-controller v1.9.3, defaults; one HTTP helm repo with a 6.0 MB index; N HelmRepository objects with interval: 1m; server-side byte/request counters; idle steady state (index unchanged), 5-minute windows.

N objects index GETs / 5 min bytes / 5 min projected / day
1 5 31.0 MB 1,440 GETs / 8.9 GB
10 50 309.7 MB 14,400 GETs / 89 GB
50 249 1.54 GB ~72,000 GETs / ~444 GB

Every one of those bytes is thrown away: the digest comparison concludes "unchanged" after each download.

Proposal

Remember the ETag / Last-Modified response headers per object (an in-memory map keyed by object UID is sufficient — a controller restart just pays one full fetch), and send If-None-Match / If-Modified-Since on the next reconcile. On 304 Not Modified, short-circuit to the existing no-op path without touching the body. When the server sends no validators, behaviour is unchanged.

GitHub Pages, S3/CloudFront, Cloudflare, nginx/static hosting and Harbor all emit validators for static index files, so the common cases are covered.

This mirrors what the controller already does for the other source kinds — GitRepository checks advertised refs before cloning, OCIRepository resolves the manifest digest via HEAD before pulling — HelmRepository/HTTP is the only kind that must download the full payload to discover nothing changed.

Happy to send the PR.

Dominant language
Go
Stars
283
Forks
252
Avg merge
1h 6m
Merged PRs (30d)
12

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from fluxcd/source-controller

All issues in fluxcd/source-controller

Similar issues

More Go issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.