{"id":42485697,"url":"https://github.com/nobl9/nobl9-go","last_synced_at":"2026-06-16T12:00:55.127Z","repository":{"id":213731529,"uuid":"395544789","full_name":"nobl9/nobl9-go","owner":"nobl9","description":"Nobl9 SDK for Go!","archived":false,"fork":false,"pushed_at":"2026-06-09T11:25:10.000Z","size":3706,"stargazers_count":29,"open_issues_count":10,"forks_count":2,"subscribers_count":5,"default_branch":"main","last_synced_at":"2026-06-09T12:21:43.073Z","etag":null,"topics":["go","golang","nobl9","reliability","sdk","slo"],"latest_commit_sha":null,"homepage":"https://www.nobl9.com","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nobl9.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"docs/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-08-13T06:35:53.000Z","updated_at":"2026-06-09T10:48:11.000Z","dependencies_parsed_at":"2024-01-13T04:50:09.185Z","dependency_job_id":"94399839-aa0a-4955-b9b8-0a70f2de8cbb","html_url":"https://github.com/nobl9/nobl9-go","commit_stats":{"total_commits":486,"total_committers":32,"mean_commits":15.1875,"dds":0.5473251028806585,"last_synced_commit":"1106a0dd88e5dc112045c955435d1f6241a086c4"},"previous_names":["nobl9/nobl9-go"],"tags_count":349,"template":false,"template_full_name":null,"purl":"pkg:github/nobl9/nobl9-go","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nobl9%2Fnobl9-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nobl9%2Fnobl9-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nobl9%2Fnobl9-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nobl9%2Fnobl9-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nobl9","download_url":"https://codeload.github.com/nobl9/nobl9-go/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nobl9%2Fnobl9-go/sbom","scorecard":{"id":363675,"data":{"date":"2025-08-11","repo":{"name":"github.com/nobl9/nobl9-go","commit":"dace3e654bccd8a94d615010df5c13115f5f4fcd"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.9,"checks":[{"name":"Maintained","score":10,"reason":"30 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 10","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":10,"reason":"all changesets reviewed","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: jobLevel 'contents' permission set to 'write': .github/workflows/release-drafter.yml:19","Warn: no topLevel permission defined: .github/workflows/checks.yml:1","Warn: no topLevel permission defined: .github/workflows/e2e-tests-dispatch.yml:1","Warn: no topLevel permission defined: .github/workflows/e2e-tests.yml:1","Warn: no topLevel permission defined: .github/workflows/pr-title.yml:1","Info: topLevel 'contents' permission set to 'read': .github/workflows/release-drafter.yml:13","Warn: no topLevel permission defined: .github/workflows/tests.yml:1","Warn: no topLevel permission defined: .github/workflows/vulns.yml:1"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/checks.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/nobl9/nobl9-go/checks.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/checks.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/nobl9/nobl9-go/checks.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/checks.yml:23: update your workflow using https://app.stepsecurity.io/secureworkflow/nobl9/nobl9-go/checks.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/checks.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/nobl9/nobl9-go/checks.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/e2e-tests.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/nobl9/nobl9-go/e2e-tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/e2e-tests.yml:46: update your workflow using https://app.stepsecurity.io/secureworkflow/nobl9/nobl9-go/e2e-tests.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/e2e-tests.yml:51: update your workflow using https://app.stepsecurity.io/secureworkflow/nobl9/nobl9-go/e2e-tests.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/pr-title.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/nobl9/nobl9-go/pr-title.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release-drafter.yml:28: update your workflow using https://app.stepsecurity.io/secureworkflow/nobl9/nobl9-go/release-drafter.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release-drafter.yml:34: update your workflow using https://app.stepsecurity.io/secureworkflow/nobl9/nobl9-go/release-drafter.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/nobl9/nobl9-go/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:21: update your workflow using https://app.stepsecurity.io/secureworkflow/nobl9/nobl9-go/tests.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/vulns.yml:18: update your workflow using https://app.stepsecurity.io/secureworkflow/nobl9/nobl9-go/vulns.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/vulns.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/nobl9/nobl9-go/vulns.yml/main?enable=pin","Info:   0 out of  11 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Mozilla Public License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GO-2022-0635","Warn: Project is vulnerable to: GO-2022-0646"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Branch-Protection","score":8,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'main'","Info: 'force pushes' disabled on branch 'main'","Warn: required approving review count is 1 on branch 'main'","Warn: codeowners review is not required on branch 'main'","Info: status check found to merge onto on branch 'main'","Info: PRs are required in order to make changes on branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 30 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-18T11:22:43.189Z","repository_id":213731529,"created_at":"2025-08-18T11:22:43.189Z","updated_at":"2025-08-18T11:22:43.189Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34404748,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-16T02:00:06.860Z","response_time":126,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","golang","nobl9","reliability","sdk","slo"],"created_at":"2026-01-28T11:27:46.551Z","updated_at":"2026-06-16T12:00:55.118Z","avatar_url":"https://github.com/nobl9.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- markdownlint-disable line-length html --\u003e\n\u003ch1 align=\"center\"\u003e\n   \u003cpicture\u003e\n      \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://github.com/nobl9/nobl9-go/assets/48822818/caa6dfd0-e4b7-4cc5-b565-b867e23988ec\"\u003e\n      \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://github.com/nobl9/nobl9-go/assets/48822818/4b0288bf-28ec-4435-af42-1d8918c81a47\"\u003e\n      \u003cimg alt=\"N9\" src=\"https://github.com/nobl9/nobl9-go/assets/48822818/4b0288bf-28ec-4435-af42-1d8918c81a47\" width=\"500\" /\u003e\n   \u003c/picture\u003e\n\u003c/h1\u003e\n\n\u003cdiv align=\"center\"\u003e\n  \u003ctable\u003e\n    \u003ctr\u003e\n      \u003ctd\u003e\n        \u003cimg alt=\"checks\" src=\"https://github.com/nobl9/nobl9-go/actions/workflows/checks.yml/badge.svg?event=push\"\u003e\n      \u003c/td\u003e\n      \u003ctd\u003e\n        \u003cimg alt=\"tests\" src=\"https://github.com/nobl9/nobl9-go/actions/workflows/tests.yml/badge.svg?event=push\"\u003e\n      \u003c/td\u003e\n      \u003ctd\u003e\n        \u003cimg alt=\"vulnerabilities\" src=\"https://github.com/nobl9/nobl9-go/actions/workflows/vulns.yml/badge.svg?event=push\"\u003e\n      \u003c/td\u003e\n    \u003c/tr\u003e\n  \u003c/table\u003e\n\u003c/div\u003e\n\u003c!-- markdownlint-enable line-length html --\u003e\n\n[Nobl9](https://www.nobl9.com/) SDK for the Go programming language.\n\nCheckout [release notes](https://github.com/nobl9/nobl9-go/releases)\nfor details on the latest bug fixes, updates, and features.\n\n⚠️ Until v1.0.0 is released, we expect some minor breaking API changes\nto be introduced.\n\n---\n\nLegend:\n\n1. [Installation](#installation)\n2. [Examples](#examples)\n3. [Usage](#usage)\n4. [Repository structure](#repository-structure)\n5. [Contributing](#contributing)\n\n# Installation\n\nTo add the latest version to your Go module run:\n\n```shell\ngo get github.com/nobl9/nobl9-go\n```\n\n# Examples\n\n## Basic usage\n\n\u003c!-- markdownlint-disable MD013 --\u003e\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"encoding/json\"\n\t\"fmt\"\n\t\"log\"\n\n\t\"github.com/nobl9/nobl9-go/manifest\"\n\t\"github.com/nobl9/nobl9-go/manifest/v1alpha\"\n\t\"github.com/nobl9/nobl9-go/manifest/v1alpha/project\"\n\t\"github.com/nobl9/nobl9-go/manifest/v1alpha/service\"\n\t\"github.com/nobl9/nobl9-go/sdk\"\n\tobjectsV2 \"github.com/nobl9/nobl9-go/sdk/endpoints/objects/v2\"\n)\n\nfunc main() {\n\tctx := context.Background()\n\n\t// Create client.\n\tclient, err := sdk.DefaultClient()\n\tif err != nil {\n\t\tlog.Fatalf(\"failed to create sdk client, err: %v\", err)\n\t}\n\n\t// Read from file, url or glob pattern.\n\tobjects, err := sdk.ReadObjects(ctx, \"./project.yaml\")\n\tif err != nil {\n\t\tlog.Fatalf(\"failed to read project.yaml file, err: %v\", err)\n\t}\n\t// Use manifest.FilterByKind to extract specific objects from the manifest.Object slice.\n\tmyProject := manifest.FilterByKind[project.Project](objects)[0]\n\t// Define objects in code.\n\tmyService := service.New(\n\t\tservice.Metadata{\n\t\t\tName:        \"my-service\",\n\t\t\tDisplayName: \"My Service\",\n\t\t\tProject:     myProject.GetName(),\n\t\t\tLabels: v1alpha.Labels{\n\t\t\t\t\"team\":   []string{\"green\", \"orange\"},\n\t\t\t\t\"region\": []string{\"eu-central-1\"},\n\t\t\t},\n\t\t},\n\t\tservice.Spec{\n\t\t\tDescription: \"Example service\",\n\t\t},\n\t)\n\tobjects = append(objects, myService)\n\n\t// Verify the objects.\n\tif errs := manifest.Validate(objects); len(errs) \u003e 0 {\n\t\tlog.Fatalf(\"service validation failed, errors: %v\", errs)\n\t}\n\n\t// Apply the objects.\n\tif err = client.Objects().V2().Apply(ctx, objectsV2.ApplyRequest{Objects: objects}); err != nil {\n\t\tlog.Fatalf(\"failed to apply objects, err: %v\", err)\n\t}\n\n\t// Get the applied resources.\n\tservices, err := client.Objects().V1().GetV1alphaServices(ctx, objectsV1.GetServicesRequest{\n\t\tProject: myProject.GetName(),\n\t\tNames:   []string{myService.GetName()},\n\t})\n\tif err != nil {\n\t\tlog.Fatalf(\"failed to get services, err: %v\", err)\n\t}\n\tprojects, err := client.Objects().V1().GetV1alphaProjects(ctx, objectsV1.GetProjectsRequest{\n\t\tNames: []string{myProject.GetName()},\n\t})\n\tif err != nil {\n\t\tlog.Fatalf(\"failed to get projects, err: %v\", err)\n\t}\n\n\t// Aggregate objects back into manifest.Objects slice.\n\tappliedObjects := make([]manifest.Object, 0, len(services)+len(projects))\n\tfor _, service := range services {\n\t\tappliedObjects = append(appliedObjects, service)\n\t}\n\tfor _, project := range projects {\n\t\tappliedObjects = append(appliedObjects, project)\n\t}\n\n\t// Print JSON representation of these objects.\n\tdata, err := json.MarshalIndent(appliedObjects, \"\", \"  \")\n\tif err != nil {\n\t\tlog.Fatalf(\"failed to marshal objects, err: %v\", err)\n\t}\n\tfmt.Println(string(data))\n\n\t// Delete resources.\n\tif err = client.Objects().V2().Delete(ctx, objectsV2.DeleteRequest{Objects: objects}); err != nil {\n\t\tlog.Fatalf(\"failed to delete objects, err: %v\", err)\n\t}\n}\n```\n\n\u003c!-- markdownlint-enable MD013 --\u003e\n\n# Usage\n\n## Reading configuration\n\nIn order for `sdk.Client` to work, it needs to be configured.\nThe configuration can be read from a file, environment variables,\ncode options or a combination of these.\n\nThe precedence of the configuration sources is as follows\n(starting from the highest):\n\n- Code options\n- Environment variables\n- Configuration file\n- Default values\n\nThe following flowchart illustrates the process of reading the configuration:\n\n```mermaid\nflowchart TD\n    subgraph s1[Read config file]\n        direction LR\n        As1{{Config file exists}} -- true --\u003e Bs1(Read config file)\n        As1 -- false --\u003e Cs1(Create default config file)\n        Cs1 --\u003e Bs1\n    end\n    subgraph s2[Build config struct]\n        direction LR\n        As2{{Has ConfigOption}} -- not set --\u003e Bs2{{Has env variable}}\n        As2 -- set --\u003e Fs2(Use value)\n        Bs2 -- not set --\u003e Cs2{{Has config file option}}\n        Bs2 -- set --\u003e Fs2\n        Cs2 -- not set --\u003e Ds2{{Has default value}}\n        Cs2 -- set --\u003e Fs2\n        Ds2 -- not set --\u003e Es2(No value)\n        Ds2 -- set --\u003e Fs2\n    end\n    A(Read config) --\u003e B(Read config options defined in code)\n    B --\u003e C(Read env variables)\n    C --\u003e s1\n    s1 --\u003e s2 --\u003e I(Return Config)\n```\n\n## Testing code relying on nobl9-go\n\nCheckout [these instructions](./docs/mock_example/README.md)\nalong with a working example for recommendations on mocking `sdk.Client`.\n\n# Repository structure\n\n## Public packages\n\n1. [sdk](./sdk) defines:\n\n    - `Client` which exposes methods for interacting with\n      different Nobl9 web APIs.\n    - Methods for reading and managing Nobl9\n      configuration (including the `config.toml` file) used by tools\n      such as `sloctl` or the SDK itself.\n    - Methods for fetching and parsing Nobl9 configuration objects.\n\n2. [manifest](./manifest) holds definitions of all Nobl9 configuration\n   objects, such as SLO or Project. It is divided into three package\n   levels:\n\n   ```text\n   └── manifest\n       └── version (e.g. v1alpha)\n           └── object (e.g. slo)\n   ```\n\n    - [manifest](./manifest) defines general contracts and generic methods\n      for all objects.\n    - Version-specific packages, such as [v1alpha](./manifest/v1alpha), define\n      version-specific APIs, functions and structures shared by multiple\n      objects.\n    - Object-specific packages, like [slo](./manifest/v1alpha/slo), provide\n      object definition for specific object versions.\n\n## Internal packages\n\n1. [tests](./tests) contains the end-to-end tests code.\n   These tests are run directly against a Nobl9 platform.\n2. [internal](./internal) holds internal packages that are not meant to be\n   exposed as part of the library's API.\n\n# Contributing\n\nCheckout both [contributing guidelines](./docs/CONTRIBUTING.md) and\n[development instructions](./docs/DEVELOPMENT.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnobl9%2Fnobl9-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnobl9%2Fnobl9-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnobl9%2Fnobl9-go/lists"}