## TL;DR
Pluto flags manifests using apiVersions your target cluster no longer serves, which would break on apply. Map each deprecated apiVersion to its replacement, update the manifests, and let CI verify the replacements are not deprecated too.

```text
deprecated apiVersion found: [APIVERSION] [KIND] [NAME]
```

## Steps

1. List every deprecated object Pluto found in the repo:
```bash
pluto detect-files -d [MANIFEST_DIR] -o wide
```
Expected: a table of each deprecated apiVersion with its kind, name, and the replacement version.

2. Check the finding against your actual target cluster version:
```bash
pluto detect-helm --namespace [NAMESPACE] --only-show-removed
```
Expected: findings scoped to APIs actually removed in the cluster you deploy to, so you do not churn on versions that are deprecated but still served.

3. Update each manifest to the replacement apiVersion from the Pluto output:
```bash
# example: extensions/v1beta1 Ingress becomes networking.k8s.io/v1
# edit [MANIFEST_FILE], changing apiVersion and any renamed fields
```
Expected: the manifest uses the replacement apiVersion with fields adjusted for the new schema.

4. Verify the updated manifests pass Pluto:
```bash
pluto detect-files -d [MANIFEST_DIR]
```
Expected: no findings, or only findings for APIs still served by your target cluster version.

5. Confirm the manifests still apply cleanly with a dry run:
```bash
kubectl apply --dry-run=server -f [MANIFEST_DIR]
```
Expected: the server accepts every manifest, proving the new apiVersions are served and the schemas validate.

## When to use
- pluto detect fails CI with deprecated apiVersion found
- You are upgrading a cluster and want to find manifests that will break
- Helm releases render deprecated APIs and the pipeline gates on it

## When not to use
- kubectl apply fails on a missing CRD; that is a missing operator, not a deprecated built-in API
- The finding is about a custom resource; Pluto only tracks built-in Kubernetes APIs
- You need to know whether the API is removed versus merely deprecated; scope with the target cluster version

## Why it happens
Kubernetes removes old apiVersions on a schedule, but manifests in git do not update themselves. Pluto compares your manifests against a built-in deprecation table, and CI gates on it so a removed API never reaches apply time, where it would fail the whole deployment.

## Edge cases
- Some replacements rename fields, not just the apiVersion; networking.k8s.io/v1 Ingress needs the new backend service structure, not a one-line version swap
- Helm charts vendored in your repo carry their own deprecated templates; update the chart version rather than hand-editing vendored files
- Pluto's table lags brand-new Kubernetes releases; cross-check the official deprecation guide for the newest removals
- `--only-show-removed` versus deprecated matters: gating CI on merely deprecated APIs creates churn for versions your cluster still serves fine

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_4PnGOfY_NH-kbZ84N8dfBA
