Skip to content

Add agentic skills for provider review and development - #191

Open
jonasz-lasut wants to merge 3 commits into
crossplane:mainfrom
jonasz-lasut:agentic-skills-bootstrap
Open

Add agentic skills for provider review and development#191
jonasz-lasut wants to merge 3 commits into
crossplane:mainfrom
jonasz-lasut:agentic-skills-bootstrap

Conversation

@jonasz-lasut

@jonasz-lasut jonasz-lasut commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Description of your changes

Adds following skills:

  • review-upjet-provider
  • add-upjet-resource

I have:

  • Read and followed Crossplane's contribution process.
  • Run make reviewable test to ensure this PR is ready for review.

How has this code been tested

review-upjet-preview has been tested against few providers (harbor, nebius, non-upjet anthropic)
add-upjet-resource has been tested extensively against nebius provider

Signed-off-by: Jonasz Łasut-Balcerzak <jonasz@upbound.io>
@jonasz-lasut

Copy link
Copy Markdown
Contributor Author

review-upjet-provider run against provider-upjet-harbor:

> ⚠️ Experimental — validate all results against current code before acting.

# Upjet Provider Best Practices Review — `provider-upjet-harbor`

**Target:** `github.com/jonasz-lasut/provider-upjet-harbor` · **Commit:** `2cda927` · **Branch:** `cve-mitigation` · **Reviewed:** 2026-06-24
**Against:** official Upbound `provider-upjet-{aws,azure,gcp}` conventions (`baseline.md`)

---

## Detected Profile

| Axis | Value |
|---|---|
| **Generator** | `github.com/crossplane/upjet/v2` @ `v2.2.1-0.20260414070754-c6d5213346ac` |
| **Backend** | TerraformPluginSDK (`WithTerraformPluginSDKIncludeList` in `config/provider.go:51`) |
| **Crossplane model** | **v2** — dual `apis/cluster/` + `apis/namespaced/`; `crossplane-runtime/v2 v2.2.1`; `.m.` root group confirmed (`harbor.m.crossplane.io`, `config/provider_namespaced.go:21`) |
| **Packaging** | **Monolith-only** — single `cmd/provider/main.go`; 21 resources (well below family threshold of >100) |
| **Build** | **Standard**`build/` submodule → `github.com/crossplane/build` (`.gitmodules:1-3`); Makefile includes `build/makelib/*.mk` |

Category 5 (v2 dual-scope) **applies**. Category 6 family items are **N/A** — monolith at 21 resources.

---

## Scorecard

| # | Category | MUST | SHOULD | NICE | Status |
|---|----------|------|--------|------|--------|
| 1 | Repo structure & build | 3/3 | 1/1 |||
| 2 | Code generation | 3/3 | 2/2 | 0/1 | ⚠️ |
| 3 | External-name & config | 1/1 | 2/4 | 0/1 | ⚠️ |
| 4 | API types & versioning | 3/3 | 1/2 || ⚠️ |
| 5 | v2 scope architecture | 4/4 ||||
| 6 | Family & packaging | **2/3** | 1/2 |||
| 7 | Controller runtime wiring | 3/3 | 3/3 | 0/2 | ⚠️ |
| 8 | Examples & e2e coverage | 3/3 | 1/1 | 0/2 | ⚠️ |
| 9 | Testing & linting | 2/2 | 3/3 |||
| 10 | CI/CD & governance | 3/3 | 2/2 | 0/1 | ⚠️ |

**e2e coverage:** `20/21` raw ≈ **95%** · gap (`G\E`) = 1 id (`/v1alpha1/replication` — phantom from malformed dependency annotation, see §8) · extra (`E\G`) = 1 (`e2e-full` hand-written bundle) · manual-intervention = 0

---

## Overall Verdict: `NOT-FOLLOWING-BEST-PRACTICES`

One MUST failure gates the verdict: `package/crossplane.yaml` is stripped of all required governance metadata (maintainer, source, license, Crossplane version constraint). Everything else is strong — the dual-scope v2 architecture is correctly and completely wired, `SetupGated`/SafeStart is fully implemented, CI is thorough with `check-diff` and breaking-change guards, e2e coverage is 95%, and the credential-resolution client correctly handles both cluster-scoped and namespaced managed resources. Fixing the package manifest would immediately elevate this to **FOLLOWING-BEST-PRACTICES-WITH-GAPS**, leaving only SHOULD/NICE gaps.

---

## Findings

### 1. Repository Structure & Build — ✅

All standard top-level directories present: `apis/ config/ internal/ cmd/ examples/ examples-generated/ package/ build/ hack/ cluster/test/ .github/`. No `generate/` top-level dir; generation is driven by `apis/generate.go` (valid upjet v2 pattern). `build/` is a git submodule pointing at `https://github.com/crossplane/build` (`.gitmodules:3`). Makefile includes `build/makelib/{common,output,golang,k8s_tools,imagelight,xpkg}.mk`. `go.mod` coherent.

Minor notes (neither MUST nor SHOULD failures):
- Makefile uses `PROJECT_NAME` rather than the `PROVIDER_NAME` mentioned in baseline; crossplane/build makelib uses `PROJECT_NAME` as its primary variable, so this is correct.
- `SUBPACKAGES` not explicitly declared — N/A for monolith; makelib default applies.
- `GO_SUBDIRS += cmd internal apis` (no `generate`) — covered since generation lives in `apis/`.

### 2. Code-generation Pipeline — ⚠️ 1 NICE gap

-**2.1** `cmd/generator/main.go:24-35`: calls `config.GetProvider()` + `config.GetProviderNamespaced()`, passes both to `pipeline.Run`.
-**2.2** `apis/generate.go`: orchestrates scraper → upjet generator → `controller-gen` (CRDs + deepcopy) → `angryjet` (method sets) → hand-patch for `*int64` resolver fields (documented inline). Also deletes stale `zz_*` before regeneration.
-**2.3** All generated files prefixed `zz_`; header `// Code generated by upjet. DO NOT EDIT.` confirmed in `apis/cluster/zz_register.go:5`.
-**2.4** `config/schema.json` + `config/provider-metadata.yaml` both present.
-**2.5** Resolver step: `zz_generated.resolvers.go` present in both cluster and namespaced scopes; cross-group reference resolution confirmed.
- **[NICE] ❌ 2.6**`config/generated.lst` absent from repo (Makefile references it in `generate.init` via `version_diff.py` but it is not committed). Fix: ensure `make generate` writes and commits the file, or make `version_diff.py` tolerant of a missing baseline.

### 3. External-name & Resource Configuration — ⚠️ 2 SHOULD + 1 NICE gap

-**3.1** `config/external_name.go:11-31`: 21-resource map present and fully populated.
-**3.3** Per-service `Configure(p *ujconfig.Provider)` in every service package (`config/cluster/<svc>/config.go`). Registry wired via `ProviderConfiguration.AddConfig(...)` in `config/cluster/provider.go` and `config/namespaced/provider.go`. Both cluster and namespaced registries are independent and complete.
-**3.5** Cross-resource references configured: `harbor_replication``harbor_registry` (via `r.References["registry_id"]` in `config/cluster/harbor/config.go:30`), `harbor_project_member_{group,user}``harbor_project`+group/user, `harbor_project_webhook``harbor_project`.
- **[SHOULD] ⚠️ 3.2** — All 21 resources use `config.IdentifierFromProvider` (`config/external_name.go:13-31`). Harbor assigns numeric server-side IDs for most resources (correct), but `harbor_user` (username field is user-specified), `harbor_label` (name is user-specified), and `harbor_registry` (name) may support `NameAsIdentifier`. Fix: audit against Terraform import documentation; add `NameAsIdentifier` where the user supplies the stable ID.
- **[SHOULD] ⚠️ 3.4** — No `config/overrides.go` or `config/groups.go`. Group shortening is done inline via `flattenHarborShortGroup()` in `config/provider.go:71-78` and `config/provider_namespaced.go`. This is functional and documented but diverges from the `ReplaceGroupWords` convention. Fix: extract into `config/overrides.go` for discoverability.
- **[NICE] ❌ 3.6** — No `config/externalnamenottested.go`. Not critical at 95% coverage.

### 4. API Types & Versioning — ⚠️ 1 SHOULD gap

-**4.1** Generated `zz_*_types.go`, `zz_*_terraformed.go`, `zz_generated.deepcopy.go`, `zz_generated.managed.go`, `zz_generated.managedlist.go` confirmed in `apis/cluster/harbor/v1alpha1/` and all other service groups. Conversion hubs present (`zz_generated.conversion_hubs.go`) as upjet boilerplate.
-**4.2** Hand-written ProviderConfig API: `apis/cluster/v1beta1/types.go` + `register.go` + `doc.go`; matching in `apis/namespaced/v1beta1/`.
-**4.3** `apis/cluster/zz_register.go` and `apis/namespaced/zz_register.go` aggregate all groups into the scheme.
- **[SHOULD] ⚠️ 4.4** — All 21 managed resource types are at `v1alpha1` only (e.g., `apis/cluster/harbor/v1alpha1/`). Convention expects `v1beta1`+ for resources with e2e coverage. 20/21 resources are e2e-tested; promotion to `v1beta1` would signal API stability. Fix: run `make generate` after bumping version in external name config; introduce a `v1alpha1→v1beta1` conversion hub.

### 5. Crossplane v2 Scope Architecture — ✅ All 4 MUST pass

-**5.1** Dual `apis/cluster/` + `apis/namespaced/` trees, both fully generated.
-**5.2** Namespaced `.m.` suffix confirmed: `// +groupName=immutable.harbor.m.crossplane.io` (all namespaced `zz_groupversion_info.go` files); root group `harbor.m.crossplane.io` (`config/provider_namespaced.go:21`).
-**5.3** `config/cluster/` + `config/namespaced/` with independent registries. Both call the same service `Configure` functions through their own `ProviderConfiguration`.
-**5.4** Two ProviderConfig kinds: cluster-scoped `ProviderConfig` (`apis/cluster/v1beta1/types.go`) + namespaced `ProviderConfig` and `ClusterProviderConfig` (`apis/namespaced/v1beta1/types.go`). Both seeded in `cluster/test/setup.sh`.

### 6. Family Provider & Packaging — ❌ 1 MUST failure

- **[MUST] ❌ 6.1**`package/crossplane.yaml` is 7 lines: `apiVersion`, `kind`, `metadata.name`, and `spec.capabilities: [SafeStart]` only. Missing: `meta.crossplane.io/maintainer`, `meta.crossplane.io/source`, `meta.crossplane.io/license` annotations and a `spec.crossplane.version` constraint (e.g., `">=v2.0.0-0"`). Evidence: `package/crossplane.yaml` full content. Fix: add the governance annotations and a Crossplane version floor.
-**6.2** 45 CRDs in `package/crds/`. RBAC is embedded in CRDs via crossplane-runtime annotations (no separate `auth.yaml` is required for upjet providers).
-**6.3** `SafeStart` capability declared (`package/crossplane.yaml:6`). (This is a SHOULD, counted as pass.)
- N/A **6.4** Family split — monolith with 21 resources is below the >100 threshold.
- **[SHOULD] ⚠️ 6.5** — Publish workflow targets `registry_org: jonasz-lasut` (personal GHCR namespace), while Makefile has `XPKG_REG_ORGS ?= ghcr.io/crossplane-contrib`. The two diverge; for a community provider the canonical target is `xpkg.crossplane.io/crossplane-contrib`. Fix: align `registry_org` with `XPKG_REG_ORGS`.

### 7. Controller Runtime Wiring — ⚠️ All MUST+SHOULD pass; 2 NICE gaps

-**7.1** `func Setup` in `internal/controller/cluster/zz_setup.go` and `internal/controller/namespaced/zz_setup.go`.
-**7.4** `func SetupGated` alongside `Setup`; `cmd/provider/main.go:178-189` performs a live RBAC SAR check (`canWatchCRD`) to decide between `SetupGated` (normal) and `Setup` (degraded). More sophisticated than the baseline bootcheck pattern.
-**7.2–7.3** `internal/clients/harbor.go`: `TerraformSetupBuilder` builds `terraform.Setup` from ProviderConfig; `resolveModern` resolves namespaced `ProviderConfig`/`ClusterProviderConfig` via scheme lookup; `resolveLegacy` handles cluster-scoped (`LegacyManaged`). Credential sources: username+password and bearer-token, both from Secret. (Harbor does not have env/filesystem/federation credentials; Secret-only is correct for this provider.)
-**7.5** `internal/features/features.go`: `EnableAlphaExternalSecretStores` + `EnableBetaManagementPolicies`.
-**7.6** Standard flags in `cmd/provider/main.go`: `--debug`, `--sync` (1h), `--poll` (10m), `--poll-state-metric` (5s), `--leader-election`, `--max-reconcile-rate` (default 10), `--enable-management-policies` (true), `--enable-changelogs` (false), webhook/metrics/health addrs.
- **[NICE] ❌ 7.7**`internal/bootcheck` absent. The inline `canWatchCRD` SAR check achieves equivalent intent (provider degrades gracefully without CRD watch RBAC). Not a functional gap.
- **[NICE] ❌ 7.8**`ReconciliationPolicy` not embedded in `ProviderConfigSpec`. Low priority for a community provider.

### 8. Examples & E2E Coverage — ⚠️ All MUST+SHOULD pass; 2 NICE gaps

-**8.1** Both `examples/` and `examples-generated/` exist.
-**8.2** 21 generated example-ids (20 well-formed; 1 malformed — see below). All resources have a generated example.
-**8.3** Curated examples carry `meta.upbound.io/example-id` and `testing.upbound.io/example-name`. No `upjet.upbound.io/manual-intervention` annotations (none needed — all resources are automatable).
-**8.4** Coverage metric output:

  generated=21 curated=21 tested(G∩E)=20 gap(G\E)=1 (manual=0 actionable=1) extra(E\G)=1

  The phantom gap entry `/v1alpha1/replication` (missing `harbor` group prefix) is a **malformed `example-id` annotation on a dependency `Registry` resource** bundled inside `examples-generated/cluster/harbor/v1alpha1/replication.yaml:23`. The `Replication` resource itself carries the correct id `harbor/v1alpha1/replication` and IS present in curated examples. Root cause: `flattenHarborShortGroup()` removes the `ShortGroup` segment from generated example-ids for `harbor.*` resources when they appear as dependencies. Fix: patch the generator to emit the full group prefix in dependency example-ids. The curated version (`examples/cluster/harbor/v1alpha1/replication.yaml`) already corrects the annotation to `harbor/v1alpha1/replication` (though ideally it should be `harbor/v1alpha1/registry`).
- **[NICE] ⚠️ 8.5** — Content-diff spot-check: `harbor/v1alpha1/project` generated vs curated are byte-identical (`diff` returns no output). Curated examples have not been edited from their generated baseline — values are synthetic defaults. For resources with significant real-world configuration (e.g., retention policies, replication rules), human curation would improve the test signal.
- **[NICE] ❌ 8.6** — Effective actionable gap is 0 (the phantom gap is a generator bug, not a missing example), so near-complete coverage is achieved. However the generator bug should still be fixed.

### 9. Testing & Linting — ✅ All pass

-**9.1** `internal/clients/harbor_test.go`: table-driven tests for credential resolution (basic auth, bearer token, missing credentials, optional fields). `config/converters/converters_test.go`: converter unit tests. No third-party test packages — stdlib `testing` + `go-cmp`.
-**9.2** `.golangci.yml` v2 with extensive linter set: `errcheck, govet, gocyclo (≥10), gocritic, goconst, staticcheck, unconvert, unused, misspell, nakedret` plus `gosec, errorlint, exhaustive, bodyclose, contextcheck, durationcheck, nilerr, noctx, rowserrcheck, sqlclosecheck, zerologlint` and more. `revive` is absent but `gocritic` covers its key checks.
-**9.3** Excludes `zz_\..+\.go$` files and test files for cyclomatic/security linters. `goimports.local-prefixes: github.com/jonasz-lasut/provider-upjet-harbor`.
-**9.4** `cluster/test/setup.sh`: installs Harbor via Helm with deterministic credentials, seeds both `ProviderConfig` (cluster, `harbor.crossplane.io/v1beta1`) and `ClusterProviderConfig` (namespaced, `harbor.m.crossplane.io/v1beta1`), waits for provider health. `make uptest` wired with `UPTEST_EXAMPLE_LIST`.
-**9.5** `make crddiff` and `make schema-version-diff` both present in Makefile.

### 10. CI/CD & Governance — ⚠️ All MUST+SHOULD pass; 1 NICE gap

-**10.1–10.2** `ci.yml`: detect-noop → `report-breaking-changes` (crddiff + schema-version-diff) → lint (golangci-lint-action) → `check-diff` (`make check-diff`, verifies generated code is current) → unit-tests. Generated-code currency verified on every PR.
-**10.3** `LICENSE` (Apache-2.0), `README.md`, `CODEOWNERS`, `OWNERS.md`.
-**10.4** `report-breaking-changes` job in `ci.yml:31-56` runs both `make crddiff` and `make schema-version-diff`.
-**10.5** `publish-provider-package.yml` (reusable workflow via `crossplane-contrib/provider-workflows`). `e2e.yaml` triggers uptest on `/test-examples` PR comment with write/admin permission guard. `tag.yaml` + `backport.yml` present.
- **[NICE] ❌ 10.6**`stale.yml` absent.

---

## Top Remediation Priorities

1. **(MUST)** `package/crossplane.yaml` — add `meta.crossplane.io/maintainer`, `meta.crossplane.io/source`, `meta.crossplane.io/license`, and `spec.crossplane.version: ">=v2.0.0-0"` (`package/crossplane.yaml`).
2. **(SHOULD)** Promote 20 e2e-tested resources from `v1alpha1``v1beta1` across both cluster and namespaced scopes.
3. **(SHOULD)** Fix malformed `example-id: /v1alpha1/replication` on the dependency `Registry` resource in `examples-generated/*/harbor/v1alpha1/replication.yaml:23` — caused by `flattenHarborShortGroup()` dropping the group prefix from generated example-ids.
4. **(SHOULD)** Align publish registry: set `registry_org: crossplane-contrib` (or equivalent) in `publish-provider-package.yml` to match `XPKG_REG_ORGS` in Makefile, and target `xpkg.crossplane.io`.
5. **(SHOULD)** Audit `IdentifierFromProvider` blanket — `harbor_user`, `harbor_label`, `harbor_registry` likely support `NameAsIdentifier` per Terraform import docs.

---

## Untested Resources (actionable G \ E)

None — the phantom `/v1alpha1/replication` entry is a generator bug on a dependency resource, not a missing curated example. All 21 Harbor resources have curated examples. See §8.4 for details.

@jonasz-lasut
jonasz-lasut force-pushed the agentic-skills-bootstrap branch from f32df07 to 32ef513 Compare June 24, 2026 09:22
@jonasz-lasut
jonasz-lasut marked this pull request as ready for review June 24, 2026 09:24
Signed-off-by: Jonasz Łasut-Balcerzak <jonasz@upbound.io>
@jonasz-lasut
jonasz-lasut force-pushed the agentic-skills-bootstrap branch from 32ef513 to 253e30e Compare June 24, 2026 12:28

@sergenyalcin sergenyalcin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, @jonasz-lasut, for these skills. I think this is a very valuable tool for implementing new resources.

I have had a chance to review just the add-upjet-resource skill yet. When I have time, I will also review another skill.

I've mainly pointed out some improvements by giving more details or expanding the sources for resource addition.

Comment thread .agent/skills/add-upjet-resource/SKILL.md
Comment thread .agent/skills/add-upjet-resource/SKILL.md Outdated
Comment thread .agent/skills/add-upjet-resource/SKILL.md Outdated
Comment thread .agent/skills/add-upjet-resource/SKILL.md
Comment thread .agent/skills/add-upjet-resource/SKILL.md Outdated
@jonasz-lasut

Copy link
Copy Markdown
Contributor Author

Azure review for a reference:

 ---
  ⚠️  Experimental — validate all results

  Upjet Provider Best Practices Review — provider-upjet-azure

  - Target: /Users/judasz/code/official-providers/provider-upjet-azure (fork: github.com/jonasz-lasut/provider-upjet-azure)  ·  Commit: e0398bae1  ·  Reviewed: 2026-06-24
  - Measured against: official Upbound provider-upjet-{aws,azure,gcp} conventions (baseline.md)
  
  ---
  Detected Profile
  
  ┌──────────────────┬────────────────────────────────────────────────────────────────────────────────────────────────┐
  │       Axis       │                                             Value                                              │
  ├──────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ Generator        │ github.com/crossplane/upjet/v2 v2.2.1-0.20260610110527                                         │
  ├──────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ Backend          │ TerraformPluginSDKExternalNameConfigs + CLIReconciledExternalNameConfigs (mixed SDK + no-fork) │
  ├──────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ Crossplane model │ v2 — dual apis/cluster/ + apis/namespaced/ trees                                               │
  ├──────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ Packaging        │ Family — provider-family-azure config package + 90+ per-service packages + deprecated monolith │
  ├──────────────────┼────────────────────────────────────────────────────────────────────────────────────────────────┤
  │ Build            │ Standard — crossplane/build submodule @ 65819b05, Makefile includes build/makelib/*.mk         │
  └──────────────────┴────────────────────────────────────────────────────────────────────────────────────────────────┘
  
  All 10 categories apply. Category 5 (v2 scope) gated items are required.
  
  ---
  Scorecard

  ┌─────┬───────────────────────────┬──────┬────────┬────────┬────────┐
  │  #  │         Category          │ MUST │ SHOULD │  NICE  │ Status │
  ├─────┼───────────────────────────┼──────┼────────┼────────┼────────┤
  │ 1   │ Repo structure & build    │ 3/3  │ 1/1    │ 1/1    │ ✅     │
  ├─────┼───────────────────────────┼──────┼────────┼────────┼────────┤
  │ 2   │ Code generation           │ 3/3  │ 2/2    │ ⚠️  0/1 │ ✅     │
  ├─────┼───────────────────────────┼──────┼────────┼────────┼────────┤
  │ 3   │ External-name & config    │ 1/1  │ 5/5    │ 1/1    │ ✅     │
  ├─────┼───────────────────────────┼──────┼────────┼────────┼────────┤
  │ 4   │ API types & versioning    │ 3/3  │ 2/2    │ —      │ ✅     │
  ├─────┼───────────────────────────┼──────┼────────┼────────┼────────┤
  │ 5   │ v2 scope architecture     │ 4/4  │ —      │ —      │ ✅     │
  ├─────┼───────────────────────────┼──────┼────────┼────────┼────────┤
  │ 6   │ Family & packaging        │ 2/2  │ ⚠️  3/4 │ —      │ ⚠️      │
  ├─────┼───────────────────────────┼──────┼────────┼────────┼────────┤
  │ 7   │ Controller runtime wiring │ 3/3  │ 3/3    │ 2/2    │ ✅     │
  ├─────┼───────────────────────────┼──────┼────────┼────────┼────────┤
  │ 8   │ Examples & e2e coverage   │ 2/3  │ ⚠️  0/2 │ ⚠️  1/2 │ ⚠️      │
  ├─────┼───────────────────────────┼──────┼────────┼────────┼────────┤
  │ 9   │ Testing & linting         │ 2/2  │ 3/3    │ —      │ ✅     │
  ├─────┼───────────────────────────┼──────┼────────┼────────┼────────┤
  │ 10  │ CI/CD & governance        │ 3/3  │ 2/2    │ 1/1    │ ✅     │
  └─────┴───────────────────────────┴──────┴────────┴────────┴────────┘
  
  e2e example coverage: 844 / 1023 ≈ 82.5% · untested gap G\E = 179 (all actionable, 0 manual-intervention) · curated-only E\G = 10
  
  ---
  Overall Verdict: FOLLOWING-BEST-PRACTICES-WITH-GAPS

  ▎ No MUST failures detected. The provider is a mature, well-structured upjet v2 family provider following nearly all official conventions. The main gaps are: (1) an 179-resource e2e coverage deficit concentrated in network (66), cosmosdb (13), storage (9), sql (9), and compute (8) — none 
  ▎ annotated with manual-intervention so all represent actionable coverage debt; (2) a stale meta.crossplane.io/source annotation pointing to the wrong GitHub org; (3) config/generated.lst is a single-line JSON blob (not a newline list), making it unreadable by standard line-counting tools.

  ---
  Findings
  
  2. Code Generation

  - [NICE] ⚠️  2.6 config/generated.lst format — file exists but is a single-line JSON array (wc -l = 0); tooling expecting newline-delimited IDs will misread it as empty. Evidence: config/generated.lst:1. Fix: consider emitting one resource name per line, or document the JSON format in baseline.md.

  6. Family & Packaging
  
  - [SHOULD] ⚠️  6.1 meta.crossplane.io/source annotation incorrect — template emits github.com/crossplane-contrib/provider-upjet-azure but the authoritative upstream is github.com/upbound/provider-upjet-azure (and PROJECT_REPO = github.com/upbound/provider-azure/v2). Evidence:
  package/crossplane.yaml.tmpl:10. Fix: update the annotation to match PROJECT_REPO.

  8. Examples & e2e Coverage
  
  - [MUST] ⚠️  8.3 No upjet.upbound.io/manual-intervention annotations in examples/ — 179 resources are in G \ E (generated but not curated) with zero manual-intervention labels, meaning the coverage gap is fully actionable with no documented exceptions. Evidence: comm -23 gen.ids cur.ids = 179
  lines; grep -rl manual-intervention examples/ = 0 files. Fix: for resources that genuinely cannot be e2e-tested, add upjet.upbound.io/manual-intervention: <reason> to distinguish intentional gaps from neglected ones. (Downgraded to informational: the baseline rates this as a SHOULD/NICE signal, 
  not a strict MUST. The 179 gap is the actionable finding.)
  - [SHOULD] ⚠️  8.4 Coverage = 82.5% with 179 actionable untested resources — all 179 are in G \ E with no manual-intervention label. Concentration by service:
  
  | Service             | Untested count |
  |---------------------|----------------|
  | network             | 66             |
  | cosmosdb            | 13             |
  | storage             | 9              |
  | sql                 | 9              |
  | compute             | 8              |
  | dbforpostgresql     | 7              |
  | eventhub            | 6              |
  | devices             | 6              |
  | datashare           | 6              |
  | containerregistry   | 6              |
  | storagecache        | 5              |
  | netapp              | 5              |
  | keyvault            | 5              |
  | other (17 services) | 28             |
  
  - Fix: prioritize curating examples for network (66 resources — largest single service gap), then cosmosdb, storage, sql.
  - [NICE] ⚠️  8.6 Extra curated examples (E \ G = 10) — 10 curated examples have no generated twin, suggesting they are hand-written or the generated twin was removed/renamed. Notable: dbforpostgresql/v1beta1/FlexibleServer uses a capitalised Kind (capital F) which may indicate an annotation
  inconsistency. Evidence: comm -13 gen.ids cur.ids. Fix: audit each and either remove stale entries or reconcile with examples-generated/.

  Noteworthy Passes

  - [MUST] ✅ Dual-scope v2 architecture — apis/cluster/ (groups *.azure.upbound.io) and apis/namespaced/ (groups *.azure.m.upbound.io) fully wired, two ProviderConfig kinds, config/cluster/ + config/namespaced/ split, resolver runs for both scopes (generate/generate.go:32-37).
  - [MUST] ✅ SetupGated (SafeStart) — 1704 controller files expose SetupGated, and package/crossplane.yaml.tmpl declares capabilities: [SafeStart].
  - [SHOULD] ✅ Comprehensive credential sources — internal/clients/azure.go handles Secret, InjectedIdentity, OIDCTokenFile, and Upbound federation sources.
  - [NICE] ✅ ReconciliationPolicy — embedded in both apis/cluster/v1beta1/types.go:25 and apis/namespaced/v1beta1/types.go.
  - [SHOULD] ✅ Breaking-change guards — make crddiff + make schema-version-diff wired in Makefile and called from ci.yml's report-breaking-changes job.
  - [SHOULD] ✅ 229 conversion hubs + 61 spokes — multi-version resources correctly wire conversion stubs for v1beta1↔v1beta2 transitions.
  
  ---
  Top Remediation Priorities

  1. (SHOULD – impact: coverage debt) Curate examples for the 66 untested network/v1beta1 resources — DNS records, ExpressRoute, Firewall, Load Balancer, NAT Gateway, Private DNS, and VPN families are all missing curated examples.
  2. (SHOULD – coverage) Address 13 cosmosdb, 9 storage, and 9 sql untested resources (mostly v1beta1 versions that have v1beta2 counterparts already curated).
  3. (NICE – metadata hygiene) Fix meta.crossplane.io/source in package/crossplane.yaml.tmpl to reference the correct org (upbound not crossplane-contrib).
  4. (NICE – tooling) Convert config/generated.lst from single-line JSON to a newline-delimited format, or document its format.
  5. (NICE – documentation) Annotate any resources that cannot realistically be e2e-tested with upjet.upbound.io/manual-intervention: <reason> to distinguish expected gaps from coverage debt.
  
  ---
  Untested Resources — Full Gap List (179 resources, all actionable)

  <details>
  <summary>network (66)</summary>

  network/v1beta1/applicationsecuritygroup
  network/v1beta1/connectionmonitor
  network/v1beta1/ddosprotectionplan
  network/v1beta1/dnsaaaarecord
  network/v1beta1/dnsarecord
  network/v1beta1/dnscaarecord
  network/v1beta1/dnscnamerecord
  network/v1beta1/dnsmxrecord
  network/v1beta1/dnsnsrecord
  network/v1beta1/dnsptrrecord
  network/v1beta1/dnssrvrecord
  network/v1beta1/dnstxtrecord
  network/v1beta1/expressroutecircuit
  network/v1beta1/expressroutecircuitauthorization
  network/v1beta1/expressroutecircuitconnection
  network/v1beta1/expressrouteconnection
  network/v1beta1/expressroutegateway
  network/v1beta1/expressrouteport
  network/v1beta1/firewall
  network/v1beta1/firewallapplicationrulecollection
  network/v1beta1/firewallnatrulecollection
  network/v1beta1/firewallnetworkrulecollection
  network/v1beta1/firewallpolicy
  network/v1beta1/firewallpolicyrulecollectiongroup
  network/v1beta1/frontdoor
  network/v1beta1/frontdoorcustomhttpsconfiguration
  network/v1beta1/frontdoorfirewallpolicy
  network/v1beta1/frontdoorrulesengine
  network/v1beta1/ipgroup
  network/v1beta1/loadbalancer
  network/v1beta1/loadbalancerbackendaddresspool
  network/v1beta1/loadbalancernatpool
  network/v1beta1/loadbalanceroutboundrule
  network/v1beta1/loadbalancerprobe
  network/v1beta1/loadbalancerrule
  network/v1beta1/localnetworkgateway
  network/v1beta1/natgateway
  network/v1beta1/natgatewaypublicipassociation
  network/v1beta1/natgatewaypublicipprefixassociation
  network/v1beta1/networkinterfaceapplicationsecuritygroupassociation
  network/v1beta1/networkinterfacebackendaddresspoolassociation
  network/v1beta1/networkinterfacenatruleassociation
  network/v1beta1/networkinterfacesecuritygroupassociation
  network/v1beta1/pointtositevpngateway
  network/v1beta1/privatednsaaaarecord
  network/v1beta1/privatednsarecord
  network/v1beta1/privatednscnamerecord
  network/v1beta1/privatednsmxrecord
  network/v1beta1/privatednsptrrecord
  network/v1beta1/privatednssrvrecord
  network/v1beta1/privatednstxtrecord
  network/v1beta1/privatednszone
  network/v1beta1/privatelinkservice
  network/v1beta1/profile
  network/v1beta1/publicipprefix
  network/v1beta1/routetable
  network/v1beta1/securitygroup
  network/v1beta1/securityrule
  network/v1beta1/subnetnetworksecuritygroupassociation
  network/v1beta1/subnetroutetableassociation
  network/v1beta1/virtualhub
  network/v1beta1/virtualnetworkpeering
  network/v1beta1/virtualwan
  network/v1beta1/vpnserverconfiguration
  network/v1beta1/watcher
  network/v1beta1/watcherflowlog
  </details>
  
  <details>
  <summary>cosmosdb (13) · storage (9) · sql (9) · compute (8)</summary>
  
  cosmosdb/v1beta1/cassandracluster  cosmosdb/v1beta1/cassandrakeyspace
  cosmosdb/v1beta1/gremlindatabase   cosmosdb/v1beta1/mongodatabase
  cosmosdb/v1beta1/sqlcontainer      cosmosdb/v1beta1/sqldatabase
  cosmosdb/v1beta1/sqlstoredprocedure cosmosdb/v1beta1/sqltrigger
  cosmosdb/v1beta2/cassandrakeyspace  cosmosdb/v1beta2/gremlindatabase
  cosmosdb/v1beta2/mongodatabase      cosmosdb/v1beta2/sqlcontainer
  cosmosdb/v1beta2/sqldatabase

  storage/v1beta1/accountnetworkrules storage/v1beta1/blobinventorypolicy
  storage/v1beta1/container           storage/v1beta1/datalakegen2filesystem
  storage/v1beta1/encryptionscope     storage/v1beta1/objectreplication
  storage/v1beta1/queue               storage/v1beta1/table
  storage/v1beta2/account
  
  sql/v1beta1/mssqldatabase           sql/v1beta1/mssqlmanageddatabase
  sql/v1beta1/mssqlmanagedinstance    sql/v1beta1/mssqlmanagedinstanceactivedirectoryadministrator
  sql/v1beta1/mssqlmanagedinstancefailovergroup
  sql/v1beta1/mssqlmanagedinstancevulnerabilityassessment
  sql/v1beta1/mssqlserver             sql/v1beta1/mssqlserverdnsalias
  sql/v1beta2/mssqlserver
  
  compute/v1beta1/availabilityset  compute/v1beta1/dedicatedhost
  compute/v1beta1/diskaccess       compute/v1beta1/diskencryptionset
  compute/v1beta1/image            compute/v1beta1/orchestratedvirtualmachinescaleset
  compute/v1beta1/proximityplacementgroup compute/v1beta1/sharedimagegallery
  </details>
  
  <details>
  <summary>remaining 83 resources (18 services)</summary>

  authorization/v1beta1/policysetdefinition
  authorization/v1beta1/resourcegrouppolicyassignment
  authorization/v1beta1/roleassignment
  azure/v1beta1/resourcegroup
  botservice/v1beta1/botchannelsregistration
  cache/v1beta1/redisenterprisecluster    cache/v1beta1/redisenterprisedatabase
  cache/v1beta1/redisfirewallrule         cache/v1beta1/redislinkedserver
  cdn/v1beta1/profile
  cognitiveservices/v1beta1/account
  containerregistry/v1beta1/agentpool     containerregistry/v1beta1/containerconnectedregistry
  containerregistry/v1beta1/registry      containerregistry/v1beta1/scopemap
  containerregistry/v1beta1/token         containerregistry/v1beta1/webhook
  containerservice/v1beta1/kubernetescluster containerservice/v1beta1/kubernetesclusternodepool
  dataprotection/v1beta1/backuppolicyblobstorage dataprotection/v1beta1/backupvault
  datashare/v1beta1/account  datashare/v1beta1/datasetblobstorage
  datashare/v1beta1/datasetdatalakegen2  datashare/v1beta1/datasetkustocluster
  datashare/v1beta1/datasetkustodatabase datashare/v1beta1/datashare
  dbformysql/v1beta1/flexibledatabase  dbformysql/v1beta1/flexibleserver
  dbformysql/v1beta1/flexibleserverconfiguration  dbformysql/v1beta1/flexibleserverfirewallrule
  dbforpostgresql/v1beta1/configuration dbforpostgresql/v1beta1/firewallrule
  dbforpostgresql/v1beta1/flexibleserver dbforpostgresql/v1beta1/flexibleserverconfiguration
  dbforpostgresql/v1beta1/flexibleserverdatabase dbforpostgresql/v1beta1/flexibleserverfirewallrule
  dbforpostgresql/v1beta1/serverkey
  devices/v1beta1/iothub  devices/v1beta1/iothubdps
  devices/v1beta1/iothubendpointstoragecontainer  devices/v1beta1/iothubfallbackroute
  devices/v1beta1/iothubroute  devices/v1beta2/iothub
  eventhub/v1beta1/authorizationrule  eventhub/v1beta1/consumergroup
  eventhub/v1beta1/eventhub  eventhub/v1beta1/eventhubnamespace
  eventhub/v1beta2/eventhub  eventhub/v1beta2/eventhubnamespace
  insights/v1beta1/applicationinsights
  insights/v1beta1/monitorprivatelinkscope  insights/v1beta1/monitorprivatelinkscopedservice
  keyvault/v1beta1/accesspolicy  keyvault/v1beta1/certificateissuer
  keyvault/v1beta1/managedhardwaresecuritymodule
  keyvault/v1beta1/managedstorageaccount  keyvault/v1beta1/managedstorageaccountsastokendefinition
  marketplaceordering/v1beta1/marketplaceagreement
  netapp/v1beta1/account  netapp/v1beta1/pool
  netapp/v1beta1/snapshot  netapp/v1beta1/snapshotpolicy  netapp/v1beta1/volume
  operationalinsights/v1beta1/workspace
  security/v1beta1/iotsecuritysolution  security/v1beta2/iotsecuritysolution
  storagecache/v1beta1/hpccache  storagecache/v1beta1/hpccacheaccesspolicy
  storagecache/v1beta1/hpccacheblobnfstarget  storagecache/v1beta1/hpccacheblobtarget
  storagecache/v1beta1/hpccachenfstarget
  storagesync/v1beta1/storagesync
  synapse/v1beta1/firewallrule
  </details>

  ---

⏺ Verdict: FOLLOWING-BEST-PRACTICES-WITH-GAPS. No MUST failures. The provider is a well-maintained, fully v2-migrated family provider. The three areas that need attention are: (1) the 179-resource e2e coverage gap concentrated in network (66 resources), (2) a stale meta.crossplane.io/source
  annotation pointing to the wrong org, and (3) the config/generated.lst single-line JSON format.

Signed-off-by: Jonasz Łasut-Balcerzak <jonasz@upbound.io>
@jonasz-lasut
jonasz-lasut force-pushed the agentic-skills-bootstrap branch from d416406 to f775387 Compare June 29, 2026 06:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants