How to Discover All OCI Helm Charts in Harbor: A Step-by-Step Guide

3 min read

Overview

If you manage a Harbor registry with dozens of projects and hundreds of repositories, answering a simple question like "what Helm charts do we have?" can be surprisingly difficult. Harbor's UI lets you browse one project at a time, but there is no built-in way to get a consolidated inventory across every project.

This post walks through a Bash script that uses the Harbor v2.0 REST API to enumerate every OCI Helm chart version across all projects and outputs a clean CSV. It is completely read-only — no charts are pulled or modified.

Prerequisites

  • bash 4+ (macOS ships with 3.x — use brew install bash if needed)
  • curl
  • jq
  • A Harbor user account with read access to the target projects

Step 1 — Clone the tool

git clone https://github.com/karankiruba09/platform-infra-automation.git
cd platform-infra-automation/kubernetes/harbor-helm-discovery

The tool is a single self-contained script: list-harbor-helm-charts.sh.

Step 2 — Set environment variables

The script accepts configuration through environment variables or positional arguments. Environment variables are the recommended approach:

export HARBOR_URL=https://harbor.example.com
export HARBOR_USER=admin
export HARBOR_PASSWORD='your-password-here'

If your Harbor instance uses a self-signed certificate, also set:

export HARBOR_INSECURE=true

Optional tuning

The following environment variables can be used to tune performance:

  • PAGE_SIZE (default: 100) — Number of items per API page
  • PARALLELISM (default: 32) — Concurrent artifact lookups per project
  • OUTPUT_CSV (default: ./output/harbor-helm-charts.csv) — Path for the output CSV file

Step 3 — Run the script

./list-harbor-helm-charts.sh

You will see per-project progress printed to stderr as it scans:

Listing OCI Helm charts from https://harbor.example.com
Using parallelism: 32
Scanning project: platform-charts (42 repositories)
Found 87 OCI Helm chart version entries in platform-charts
Scanning project: infra (18 repositories)
Found 34 OCI Helm chart version entries in infra
...

Step 4 — Review the output

The script produces two files:

CSV file

Located at output/harbor-helm-charts.csv by default:

project,repository,version
"platform-charts","platform-charts/nginx-ingress","4.10.1"
"platform-charts","platform-charts/nginx-ingress","4.9.0"
"infra","infra/cert-manager","1.14.5"
...

Each row represents a single tagged chart version. If a chart artifact has no tags, it appears as <untagged>.

Totals file

Located at output/harbor-helm-charts.total.txt:

total_oci_helm_chart_versions,515

This gives you a quick count without needing to parse the CSV.

How it works

The script follows a three-level pagination pattern through the Harbor v2.0 API:

  1. ProjectsGET /api/v2.0/projects with page/page_size parameters. Each project includes a repo_count field; projects with zero repositories are skipped.
  2. Repositories — For each project, GET /api/v2.0/projects/{project}/repositories retrieves all repository names.
  3. Artifacts — For each repository, GET /api/v2.0/projects/{project}/repositories/{repo}/artifacts?with_tag=true returns artifacts with their tags. The script filters for OCI Helm charts by checking three fields: type == "CHART", or artifact_type / media_type matching application/vnd.cncf.helm.config.v1+json.

Artifact lookups are parallelized within each project using xargs -P (default: 32 concurrent workers), which keeps the scan fast even against registries with thousands of repositories.

Use cases

  • Audit and compliance — generate a full inventory of Helm charts stored in your registry for change management or security review
  • Migration planning — when moving to a new registry or upgrading Harbor, know exactly what needs to be migrated
  • Cleanup — identify stale or untagged chart versions that can be garbage-collected
  • Reporting — feed the CSV into a dashboard or spreadsheet to track chart sprawl over time

Tips

  • The script is read-only — it only issues GET requests against the Harbor API. It does not pull, push, or delete anything.
  • If you have a large registry (1000+ repositories), consider increasing PAGE_SIZE to reduce the number of API round-trips.
  • For very large scans, you can redirect stdout to a file separately from the progress output on stderr:
./list-harbor-helm-charts.sh > full-output.csv 2>progress.log

The CSV output is also printed to stdout, so you can pipe it directly into other tools:

./list-harbor-helm-charts.sh 2>/dev/null | sort -t, -k1,1
Share