Skip to content

feat(scorecards): add package covering Teams, Scorecards, Collections NGEP resources - #1433

Open
pranav-new-relic wants to merge 1 commit into
mainfrom
feat/scorecards-package
Open

feat(scorecards): add package covering Teams, Scorecards, Collections NGEP resources#1433
pranav-new-relic wants to merge 1 commit into
mainfrom
feat/scorecards-package

Conversation

@pranav-new-relic

@pranav-new-relic pranav-new-relic commented Jul 15, 2026

Copy link
Copy Markdown
Member

BROKEN - To be manually fixed by @pranav-new-relic

Summary

Adds pkg/scorecards, a single package for the four NGEP (New Relic Entity Platform) resource families that share the entityManagement* GraphQL surface:

  • Team (TEAM)
  • Scorecard (SCORECARD)
  • ScorecardRule (SCORECARD_RULE)
  • Collection (COLLECTION) — including the backing collections auto-created for Teams (membership, ownership) and Scorecards (rules)

The package name is provisional — it groups these resources because they share the same interface, mutations, and reads, and interoperate (Teams/Scorecards own backing Collections; Collections are the join layer between Scorecards and ScorecardRules).

Mind map — how the pieces fit

                        ┌────────────────────────────────────────┐
                        │            ORGANIZATION                │
                        │  (scope.type=ORGANIZATION, id=orgUUID) │
                        └─────────────────┬──────────────────────┘
                                          │ scope
                ┌─────────────────────────┼─────────────────────────┐
                │                         │                         │
        ┌───────▼─────────┐    ┌──────────▼─────────┐   ┌───────────▼──────────┐
        │      TEAM       │    │     SCORECARD      │   │      COLLECTION      │
        │  (parentId → )  │    │                    │   │  (user-created,      │
        │        │        │    │                    │   │   heterogeneous)     │
        │        ▼        │    │                    │   └───────┬──────────────┘
        │   TEAM (parent) │    │                    │           │ contains
        └──┬──────────┬───┘    └──────┬─────────────┘           │
           │ auto     │ auto          │ auto                    ▼
           ▼          ▼               ▼                    any EntityManagementEntity
    ┌──────────┐ ┌──────────┐   ┌──────────┐              (USER, APM APP, TEAM, RULE, …)
    │COLLECTION│ │COLLECTION│   │COLLECTION│
    │membership│ │ownership │   │  rules   │
    └────┬─────┘ └──────────┘   └────┬─────┘
         │ contains                  │ contains
         ▼                           ▼
    USER, APM APP, etc.        SCORECARD_RULE ────► standalone lifecycle
                                                    (survives scorecard delete)

    TEAM.managers ⊂ TEAM.membership.members

What goes where

File Purpose Regenerable?
pkg/scorecards/NGEP_ANALYSIS.md Full API analysis (11 sections): entity inventory, relationship diagram, mutation matrix, per-field update semantics, cascade behaviour, transient-error taxonomy Doc
pkg/scorecards/README.md Package usage guide with code examples for each resource Doc
pkg/scorecards/scorecards.go Client constructor (scorecards.New(cfg) Scorecards); mirrors the pipelinecontrol template Hand-written
pkg/scorecards/scorecards_api.go 30 CRUD/read methods across all resources Tutone-generated + post-processed
pkg/scorecards/types.go ~10 900 lines of typed inputs/results, EntityManagement interface + implementations Tutone-generated
pkg/scorecards/scorecards_collection_members.go Add/RemoveCollectionMembers hand-written because tutone can't emit valid Go for [ID] scalar-list return Hand-written
pkg/scorecards/scorecards_types_extra.go Adds EntityManagementCollectionElementsFilter/CollectionIdFilterArgument inputs + UnmarshalJSON on EntityManagementActorStitchedFields (dispatches the polymorphic entity interface field via __typename) Hand-written
pkg/scorecards/scorecards_test.go newMockClient / newIntegrationTestClient helpers (matches pipelinecontrol_test.go shape) Hand-written
pkg/scorecards/scorecards_unit_test.go 12 unit tests using mocked NerdGraph responses; covers create/update/get/delete for each entity type + slot-aligned member ops Hand-written
pkg/scorecards/scorecards_integration_test.go 3 integration tests exercising real API CRUD + cross-entity linkage, retrying past known transient backend flakes Hand-written
.tutone.yml Adds the scorecards package block with include_implementations scoped to 8 relevant types and field_type_override pointer fixes for optional nested inputs (see below) Config
newrelic/newrelic.go Wires the client as NewRelic.Scorecards 3-line change
pkg/testhelpers/helpers.go Adds GetTestOrganizationID() for the ORG-scoped integration tests 14-line addition

Non-obvious decisions baked into the code

  1. Auto-collections are exposed as fieldsTeam.membership, Team.ownership, Scorecard.rules — their IDs are stable across parent updates and cannot be deleted directly. Consumers should treat them as read-only handles for AddCollectionMembers.
  2. managers requires NGEP-encoded user IDs, not raw int userIds. The user must first be added to the team's membership Collection.
  3. version: 0 triggers Concurrent modification of entity — every generated Update* and Delete method has the version parameter stripped (matches the manual patch already living in pkg/pipelinecontrol). Documented in the README and in the .tutone.yml block. Regeneration recipe is captured in NGEP_ANALYSIS.md § 11.
  4. Nested input structs must be pointers — Go's omitempty does not elide a zero-valued struct, so externalIntegration, schedule, and nrqlEngine would otherwise be transmitted as {"":""} on Team creation with just a name. Fixed via field_type_override: "*..." in .tutone.yml (mirrors the fleetcontrol pattern for FleetControlOperatingSystemCreateInput).
  5. Cascade — deleting a Team removes its backing Collections; deleting a Scorecard removes only its rules Collection and leaves the ScorecardRule entities orphaned. Deleting a Collection detaches (does not delete) its members.
  6. Progress levels are effectively immutable via update — backend bug (Unknown type 'EntityManagementScorecardRuleEntity' during validate). Documented and worked around by treating them as create-time-only.
  7. Two documented transient flakes the integration tests retry through: (a) ghost NOT_FOUND immediately after create (empty id prefix), (b) Concurrent modification of entity on the second write, plus a soft-skip for Oops! Something went wrong on collectionElements reads against a fresh empty collection.

Test plan

  • go build ./... clean
  • go vet ./... clean
  • go test -tags unit ./pkg/scorecards/... — 12/12 pass
  • go test -tags integration ./pkg/scorecards/... — 3/3 pass against a live org (fb33fea3-4d7e-4736-9701-acb59a634fdf); Team CRUD, Scorecard+Rule CRUD with cross-linkage, Collection CRUD
  • Regen recipe verified: fetch → generate --packages scorecards → post-processor strips version args → build passes
  • Client registered on newrelic.NewRelic.Scorecards

Follow-ups (not blocking this PR)

  • Hierarchy mutations (entityManagementCreateTeamsHierarchyLevel, entityManagementCreateTeamsOrganizationSettings) are omitted because tutone's introspection dump misses their CreateInput types (they're also RBAC-gated in most orgs). Update variants are wired; re-add Creates once tutone fetch is patched.
  • The Add/RemoveCollectionMembers and the missing filter input types can move back into tutone-generated code once the upstream template supports scalar-list mutation returns and full input-type coverage.
  • The two backend bugs referenced above (progressLevels update, collectionElements on fresh Collections) are worth reporting to the NGEP team.

… NGEP resources

Introduces pkg/scorecards, a single package for the four NGEP resource
families that share the entityManagement GraphQL surface: Team,
Scorecard, ScorecardRule, and Collection (including the auto-created
membership/ownership/rules backing collections attached to Teams and
Scorecards).

Live-API exploration drove the design — see NGEP_ANALYSIS.md for the
mind-map, per-field update semantics, cascade behaviour, and the
transient-error taxonomy the integration tests retry through.
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 53.38645% with 117 lines in your changes missing coverage. Please review.
✅ Project coverage is 33.13%. Comparing base (55e6cd2) to head (94e74c2).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
pkg/scorecards/scorecards_api.go 48.10% 87 Missing and 9 partials ⚠️
pkg/scorecards/scorecards_types_extra.go 45.83% 8 Missing and 5 partials ⚠️
pkg/testhelpers/helpers.go 0.00% 5 Missing ⚠️
pkg/scorecards/scorecards_collection_members.go 89.65% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1433      +/-   ##
==========================================
+ Coverage   32.39%   33.13%   +0.73%     
==========================================
  Files         148      152       +4     
  Lines        6923     7174     +251     
==========================================
+ Hits         2243     2377     +134     
- Misses       4467     4569     +102     
- Partials      213      228      +15     
Flag Coverage Δ
unit 33.13% <53.38%> (+0.73%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@pranav-new-relic
pranav-new-relic force-pushed the feat/scorecards-package branch from 29d22fb to 94e74c2 Compare July 15, 2026 18:27
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