Skip to content

Commit 1ccf047

Browse files
Add ServiceStats to Service (#562)
* Add ServiceStats to Service Add GetServiceStats to Service, which returns Rubric and the checks / levels associated with that for a given service. * Update .changes/unreleased/Feature-20250606-102556.yaml Co-authored-by: Kyle <kyle@opslevel.com> * Changelog for CheckResult breaking change Replacing Check with CheckId on CheckResult is a breaking change, add a note about that --------- Co-authored-by: Kyle <kyle@opslevel.com>
1 parent 095e4b0 commit 1ccf047

16 files changed

Lines changed: 386 additions & 58 deletions
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
kind: Feature
2+
body: "Add `client.GetServiceStats` function, which includes Rubric and CheckResults data to retrieve maturity report information for a service"
3+
time: 2025-06-06T10:25:56.068277-04:00
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
kind: Removed
2+
body: Breaking change: Removed Check from CheckResult and replaced with CheckId. This prevents loops when working with Level
3+
time: 2025-06-06T15:11:54.322534-04:00

cache_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func TestCache(t *testing.T) {
3535
`{"data":{"account":{"rubric":{ "categories":{ "nodes":[{{ template "category_1" }}] } }}}}`,
3636
)
3737
testRequestSix := autopilot.NewTestRequest(
38-
`query LevelsList($after:String!$first:Int!){account{rubric{levels(after: $after, first: $first){nodes{alias,description,id,index,name},{{ template "pagination_request" }}}}}}`,
38+
`query LevelsList($after:String!$first:Int!){account{rubric{levels(after: $after, first: $first){nodes{alias,checks{id,name},description,id,index,name},{{ template "pagination_request" }}}}}}`,
3939
`{ "after": "", "first": 100 }`,
4040
`{"data":{"account":{"rubric":{ "levels":{ "nodes":[{{ template "level_1" }}] } }}}}`,
4141
)

check.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ import (
1010
"github.com/relvacode/iso8601"
1111
)
1212

13+
type CheckId struct {
14+
Id ID `json:"id"`
15+
Name string `json:"name"`
16+
}
17+
1318
type CheckInputConstructor func() any
1419

1520
var CheckCreateConstructors = map[CheckType]CheckInputConstructor{

check_test.go

Lines changed: 5 additions & 5 deletions
Large diffs are not rendered by default.

connection.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ type CategoryConnection ConnectionBase[Category]
3131
// CheckConnection The connection type for Check
3232
type CheckConnection ConnectionBase[Check]
3333

34+
// CheckResultsByLevelConnection The connection type for CheckResultsByLevel
35+
type CheckResultsByLevelConnection ConnectionBase[CheckResultsByLevel]
36+
37+
// CheckResultsConnection The connection type for CheckResult
38+
type CheckResultsConnection ConnectionBase[CheckResult]
39+
3440
// ComponentTypeConnection The connection type for ComponentType
3541
type ComponentTypeConnection ConnectionBase[ComponentType]
3642

@@ -85,9 +91,15 @@ type ScorecardCheckConnection ConnectionBase[Check]
8591
// ScorecardConnection The connection type for Scorecard
8692
type ScorecardConnection ConnectionBase[Scorecard]
8793

94+
// ScorecardStatsConnection The connection type for ScorecardStats
95+
type ScorecardStatsConnection ConnectionBase[ScorecardStats]
96+
8897
// SecretsVaultsSecretsConnection The connection type for Secret
8998
type SecretsVaultsSecretsConnection ConnectionBase[Secret]
9099

100+
// ServiceCategoryConnection The connection type for Category
101+
type ServiceCategoryConnection ConnectionBase[Category]
102+
91103
// ServiceConnection The connection type for Service
92104
type ServiceConnection ConnectionBase[Service]
93105

document_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
func TestServiceApiDocSettingsUpdate(t *testing.T) {
1212
// Arrange
1313
testRequest := autopilot.NewTestRequest(
14-
`mutation ServiceApiDocSettingsUpdate($docPath:String$docSource:ApiDocumentSourceEnum$service:IdentifierInput!){serviceApiDocSettingsUpdate(service: $service, apiDocumentPath: $docPath, preferredApiDocumentSource: $docSource){service{apiDocumentPath,description,framework,htmlUrl,id,aliases,language,lifecycle{alias,description,id,index,name},locked,managedAliases,maturityReport{overallLevel{alias,description,id,index,name}},name,note,owner{alias,id},parent{id,aliases},preferredApiDocument{id,htmlUrl,source{... on ApiDocIntegration{id,name,type},... on ServiceRepository{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}}},timestamps{createdAt,updatedAt}},preferredApiDocumentSource,product,repos{edges{node{id,defaultAlias},serviceRepositories{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}}},{{ template "pagination_request" }}},defaultServiceRepository{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}},tags{nodes{id,key,value},{{ template "pagination_request" }}},tier{alias,description,id,index,name},timestamps{createdAt,updatedAt},tools{nodes{category,categoryAlias,displayName,environment,id,service{id,aliases},url},{{ template "pagination_request" }}},type{id,aliases}},errors{message,path}}}`,
14+
`mutation ServiceApiDocSettingsUpdate($docPath:String$docSource:ApiDocumentSourceEnum$service:IdentifierInput!){serviceApiDocSettingsUpdate(service: $service, apiDocumentPath: $docPath, preferredApiDocumentSource: $docSource){service{apiDocumentPath,description,framework,htmlUrl,id,aliases,language,lifecycle{alias,description,id,index,name},locked,managedAliases,maturityReport{overallLevel{alias,checks{id,name},description,id,index,name}},name,note,owner{alias,id},parent{id,aliases},preferredApiDocument{id,htmlUrl,source{... on ApiDocIntegration{id,name,type},... on ServiceRepository{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}}},timestamps{createdAt,updatedAt}},preferredApiDocumentSource,product,repos{edges{node{id,defaultAlias},serviceRepositories{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}}},{{ template "pagination_request" }}},defaultServiceRepository{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}},tags{nodes{id,key,value},{{ template "pagination_request" }}},tier{alias,description,id,index,name},timestamps{createdAt,updatedAt},tools{nodes{category,categoryAlias,displayName,environment,id,service{id,aliases},url},{{ template "pagination_request" }}},type{id,aliases}},errors{message,path}}}`,
1515
`{"docPath":"/src/swagger.json", "docSource":"PULL", "service": {"alias":"service_alias" }}`,
1616
`{"data": {"serviceApiDocSettingsUpdate": {"service": {{ template "service_1" }}, "errors": [] }}}`,
1717
)
@@ -30,7 +30,7 @@ func TestServiceApiDocSettingsUpdate(t *testing.T) {
3030
func TestServiceApiDocSettingsUpdateDocSourceNull(t *testing.T) {
3131
// Arrange
3232
testRequest := autopilot.NewTestRequest(
33-
`mutation ServiceApiDocSettingsUpdate($docPath:String$docSource:ApiDocumentSourceEnum$service:IdentifierInput!){serviceApiDocSettingsUpdate(service: $service, apiDocumentPath: $docPath, preferredApiDocumentSource: $docSource){service{apiDocumentPath,description,framework,htmlUrl,id,aliases,language,lifecycle{alias,description,id,index,name},locked,managedAliases,maturityReport{overallLevel{alias,description,id,index,name}},name,note,owner{alias,id},parent{id,aliases},preferredApiDocument{id,htmlUrl,source{... on ApiDocIntegration{id,name,type},... on ServiceRepository{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}}},timestamps{createdAt,updatedAt}},preferredApiDocumentSource,product,repos{edges{node{id,defaultAlias},serviceRepositories{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}}},{{ template "pagination_request" }}},defaultServiceRepository{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}},tags{nodes{id,key,value},{{ template "pagination_request" }}},tier{alias,description,id,index,name},timestamps{createdAt,updatedAt},tools{nodes{category,categoryAlias,displayName,environment,id,service{id,aliases},url},{{ template "pagination_request" }}},type{id,aliases}},errors{message,path}}}`,
33+
`mutation ServiceApiDocSettingsUpdate($docPath:String$docSource:ApiDocumentSourceEnum$service:IdentifierInput!){serviceApiDocSettingsUpdate(service: $service, apiDocumentPath: $docPath, preferredApiDocumentSource: $docSource){service{apiDocumentPath,description,framework,htmlUrl,id,aliases,language,lifecycle{alias,description,id,index,name},locked,managedAliases,maturityReport{overallLevel{alias,checks{id,name},description,id,index,name}},name,note,owner{alias,id},parent{id,aliases},preferredApiDocument{id,htmlUrl,source{... on ApiDocIntegration{id,name,type},... on ServiceRepository{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}}},timestamps{createdAt,updatedAt}},preferredApiDocumentSource,product,repos{edges{node{id,defaultAlias},serviceRepositories{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}}},{{ template "pagination_request" }}},defaultServiceRepository{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}},tags{nodes{id,key,value},{{ template "pagination_request" }}},tier{alias,description,id,index,name},timestamps{createdAt,updatedAt},tools{nodes{category,categoryAlias,displayName,environment,id,service{id,aliases},url},{{ template "pagination_request" }}},type{id,aliases}},errors{message,path}}}`,
3434
`{"docPath":"/src/swagger.json", "docSource": null, "service": {"alias":"service_alias" }}`,
3535
`{"data": { "serviceApiDocSettingsUpdate": { "service": {{ template "service_1" }}, "errors": [] }}}`,
3636
)
@@ -48,7 +48,7 @@ func TestServiceApiDocSettingsUpdateDocSourceNull(t *testing.T) {
4848
func TestServiceApiDocSettingsUpdateDocPathNull(t *testing.T) {
4949
// Arrange
5050
testRequest := autopilot.NewTestRequest(
51-
`mutation ServiceApiDocSettingsUpdate($docPath:String$docSource:ApiDocumentSourceEnum$service:IdentifierInput!){serviceApiDocSettingsUpdate(service: $service, apiDocumentPath: $docPath, preferredApiDocumentSource: $docSource){service{apiDocumentPath,description,framework,htmlUrl,id,aliases,language,lifecycle{alias,description,id,index,name},locked,managedAliases,maturityReport{overallLevel{alias,description,id,index,name}},name,note,owner{alias,id},parent{id,aliases},preferredApiDocument{id,htmlUrl,source{... on ApiDocIntegration{id,name,type},... on ServiceRepository{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}}},timestamps{createdAt,updatedAt}},preferredApiDocumentSource,product,repos{edges{node{id,defaultAlias},serviceRepositories{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}}},{{ template "pagination_request" }}},defaultServiceRepository{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}},tags{nodes{id,key,value},{{ template "pagination_request" }}},tier{alias,description,id,index,name},timestamps{createdAt,updatedAt},tools{nodes{category,categoryAlias,displayName,environment,id,service{id,aliases},url},{{ template "pagination_request" }}},type{id,aliases}},errors{message,path}}}`,
51+
`mutation ServiceApiDocSettingsUpdate($docPath:String$docSource:ApiDocumentSourceEnum$service:IdentifierInput!){serviceApiDocSettingsUpdate(service: $service, apiDocumentPath: $docPath, preferredApiDocumentSource: $docSource){service{apiDocumentPath,description,framework,htmlUrl,id,aliases,language,lifecycle{alias,description,id,index,name},locked,managedAliases,maturityReport{overallLevel{alias,checks{id,name},description,id,index,name}},name,note,owner{alias,id},parent{id,aliases},preferredApiDocument{id,htmlUrl,source{... on ApiDocIntegration{id,name,type},... on ServiceRepository{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}}},timestamps{createdAt,updatedAt}},preferredApiDocumentSource,product,repos{edges{node{id,defaultAlias},serviceRepositories{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}}},{{ template "pagination_request" }}},defaultServiceRepository{baseDirectory,displayName,id,repository{id,defaultAlias},service{id,aliases}},tags{nodes{id,key,value},{{ template "pagination_request" }}},tier{alias,description,id,index,name},timestamps{createdAt,updatedAt},tools{nodes{category,categoryAlias,displayName,environment,id,service{id,aliases},url},{{ template "pagination_request" }}},type{id,aliases}},errors{message,path}}}`,
5252
`{"docPath":null, "docSource":"PULL", "service": {"alias":"service_alias" }}`,
5353
`{"data": { "serviceApiDocSettingsUpdate": { "service": {{ template "service_1" }}, "errors": [] }}}`,
5454
)

level_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99

1010
func TestCreateRubricLevels(t *testing.T) {
1111
testRequest := autopilot.NewTestRequest(
12-
`mutation LevelCreate($input:LevelCreateInput!){levelCreate(input: $input){level{alias,description,id,index,name},errors{message,path}}}`,
12+
`mutation LevelCreate($input:LevelCreateInput!){levelCreate(input: $input){level{alias,checks{id,name},description,id,index,name},errors{message,path}}}`,
1313
`{"input": { "name": "Kyle", "description": "Created By Kyle", "index": 4 }}`,
1414
`{"data": { "levelCreate": { "level": { "alias": "kyle", "description": "Created By Kyle", "id": "Z2lkOi8vb3BzbGV2ZWwvTGV2ZWwvNDgw", "index": 4, "name": "Kyle" }, "errors": [] }}}`,
1515
)
@@ -30,7 +30,7 @@ func TestCreateRubricLevels(t *testing.T) {
3030
func TestGetRubricLevel(t *testing.T) {
3131
// Arrange
3232
testRequest := autopilot.NewTestRequest(
33-
`query LevelGet($id:ID!){account{level(id: $id){alias,description,id,index,name}}}`,
33+
`query LevelGet($id:ID!){account{level(id: $id){alias,checks{id,name},description,id,index,name}}}`,
3434
`{"id": "Z2lkOi8vb3BzbGV2ZWwvQ2hlY2tsaXN0LzYyMg"}`,
3535
`{"data": {
3636
"account": {
@@ -54,7 +54,7 @@ func TestGetRubricLevel(t *testing.T) {
5454
func TestGetMissingRubricLevel(t *testing.T) {
5555
// Arrange
5656
testRequest := autopilot.NewTestRequest(
57-
`query LevelGet($id:ID!){account{level(id: $id){alias,description,id,index,name}}}`,
57+
`query LevelGet($id:ID!){account{level(id: $id){alias,checks{id,name},description,id,index,name}}}`,
5858
`{"id": "Z2lkOi8vb3BzbGV2ZWwvQ2hlY2tsaXN0LzYyMg"}`,
5959
`{"data": { "account": { "level": null }}}`,
6060
)
@@ -69,7 +69,7 @@ func TestGetMissingRubricLevel(t *testing.T) {
6969
func TestListRubricLevels(t *testing.T) {
7070
// Arrange
7171
testRequest := autopilot.NewTestRequest(
72-
`query LevelsList($after:String!$first:Int!){account{rubric{levels(after: $after, first: $first){nodes{alias,description,id,index,name},{{ template "pagination_request" }}}}}}`,
72+
`query LevelsList($after:String!$first:Int!){account{rubric{levels(after: $after, first: $first){nodes{alias,checks{id,name},description,id,index,name},{{ template "pagination_request" }}}}}}`,
7373
`{"after":"","first":100}`,
7474
`{
7575
"data": {
@@ -124,7 +124,7 @@ func TestListRubricLevels(t *testing.T) {
124124
func TestUpdateRubricLevel(t *testing.T) {
125125
// Arrange
126126
testRequest := autopilot.NewTestRequest(
127-
`mutation LevelUpdate($input:LevelUpdateInput!){levelUpdate(input: $input){level{alias,description,id,index,name},errors{message,path}}}`,
127+
`mutation LevelUpdate($input:LevelUpdateInput!){levelUpdate(input: $input){level{alias,checks{id,name},description,id,index,name},errors{message,path}}}`,
128128
`{"input": { {{ template "id1" }}, "name": "{{ template "name1" }}", "description": "{{ template "description" }}" }}`,
129129
`{"data": { "levelUpdate": { "level": {{ template "level_1" }}, "errors": [] }}}`,
130130
)
@@ -145,7 +145,7 @@ func TestUpdateRubricLevel(t *testing.T) {
145145
func TestUpdateRubricLevelNoName(t *testing.T) {
146146
// Arrange
147147
testRequest := autopilot.NewTestRequest(
148-
`mutation LevelUpdate($input:LevelUpdateInput!){levelUpdate(input: $input){level{alias,description,id,index,name},errors{message,path}}}`,
148+
`mutation LevelUpdate($input:LevelUpdateInput!){levelUpdate(input: $input){level{alias,checks{id,name},description,id,index,name},errors{message,path}}}`,
149149
`{"input": { {{ template "id1" }}, "description": "{{ template "description" }}" } }`,
150150
`{"data": { "levelUpdate": { "level": {{ template "level_1" }}, "errors": [] }}}`,
151151
)
@@ -165,7 +165,7 @@ func TestUpdateRubricLevelNoName(t *testing.T) {
165165
func TestUpdateRubricLevelEmptyDescription(t *testing.T) {
166166
// Arrange
167167
testRequest := autopilot.NewTestRequest(
168-
`mutation LevelUpdate($input:LevelUpdateInput!){levelUpdate(input: $input){level{alias,description,id,index,name},errors{message,path}}}`,
168+
`mutation LevelUpdate($input:LevelUpdateInput!){levelUpdate(input: $input){level{alias,checks{id,name},description,id,index,name},errors{message,path}}}`,
169169
`{"input": { {{ template "id1" }}, "name": "{{ template "name1" }}", "description": "" }}`,
170170
`{"data": { "levelUpdate": { "level": {{ template "level_1" }}, "errors": [] }}}`,
171171
)
@@ -186,7 +186,7 @@ func TestUpdateRubricLevelEmptyDescription(t *testing.T) {
186186
func TestUpdateRubricLevelNoDescription(t *testing.T) {
187187
// Arrange
188188
testRequest := autopilot.NewTestRequest(
189-
`mutation LevelUpdate($input:LevelUpdateInput!){levelUpdate(input: $input){level{alias,description,id,index,name},errors{message,path}}}`,
189+
`mutation LevelUpdate($input:LevelUpdateInput!){levelUpdate(input: $input){level{alias,checks{id,name},description,id,index,name},errors{message,path}}}`,
190190
`{"input": { {{ template "id1" }}, "name": "{{ template "name1" }}" }}`,
191191
`{"data": { "levelUpdate": { "level": {{ template "level_1" }}, "errors": [] }}}`,
192192
)

maturity_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
func TestGetServiceMaturityWithAlias(t *testing.T) {
1010
// Arrange
1111
testRequest := autopilot.NewTestRequest(
12-
`query ($service:String!){account{service(alias:$service){name,maturityReport{categoryBreakdown{category{description,id,name},level{alias,description,id,index,name}},overallLevel{alias,description,id,index,name}}}}}`,
12+
`query ($service:String!){account{service(alias:$service){name,maturityReport{categoryBreakdown{category{description,id,name},level{alias,checks{id,name},description,id,index,name}},overallLevel{alias,checks{id,name},description,id,index,name}}}}}`,
1313
`{"service": "cert-manager"}`,
1414
`{
1515
"data": {
@@ -133,7 +133,7 @@ func TestGetServiceMaturityWithAlias(t *testing.T) {
133133
func TestListServicesMaturity(t *testing.T) {
134134
// Arrange
135135
testRequest := autopilot.NewTestRequest(
136-
`query ServiceMaturityList($after:String!$first:Int!){account{services(after: $after, first: $first){nodes{name,maturityReport{categoryBreakdown{category{description,id,name},level{alias,description,id,index,name}},overallLevel{alias,description,id,index,name}}},{{ template "pagination_request" }}}}}`,
136+
`query ServiceMaturityList($after:String!$first:Int!){account{services(after: $after, first: $first){nodes{name,maturityReport{categoryBreakdown{category{description,id,name},level{alias,checks{id,name},description,id,index,name}},overallLevel{alias,checks{id,name},description,id,index,name}}},{{ template "pagination_request" }}}}}`,
137137
`{"after":"", "first":100}`,
138138
`{
139139
"data": {

0 commit comments

Comments
 (0)