{"id":16260033,"url":"https://github.com/cludden/concourse-go-sdk","last_synced_at":"2025-08-27T19:05:06.617Z","repository":{"id":40574314,"uuid":"472128495","full_name":"cludden/concourse-go-sdk","owner":"cludden","description":"a minimal SDK for implementing an idiomatic Concourse custom resource type in go","archived":false,"fork":false,"pushed_at":"2023-05-22T15:46:30.000Z","size":86,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-02-14T10:17:53.190Z","etag":null,"topics":["concourse","concourse-ci","concourse-resource","framework","go","golang","lib","library","resource","sdk","sdk-go"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cludden.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-03-20T23:30:37.000Z","updated_at":"2023-03-02T12:43:20.000Z","dependencies_parsed_at":"2024-11-04T21:40:31.801Z","dependency_job_id":"8bcf9ba8-a1df-427a-8956-03576a71afcd","html_url":"https://github.com/cludden/concourse-go-sdk","commit_stats":{"total_commits":12,"total_committers":2,"mean_commits":6.0,"dds":"0.33333333333333337","last_synced_commit":"9610b99e620ed9c8a345eac62efdab5f142e7544"},"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cludden%2Fconcourse-go-sdk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cludden%2Fconcourse-go-sdk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cludden%2Fconcourse-go-sdk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cludden%2Fconcourse-go-sdk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cludden","download_url":"https://codeload.github.com/cludden/concourse-go-sdk/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247854501,"owners_count":21007350,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["concourse","concourse-ci","concourse-resource","framework","go","golang","lib","library","resource","sdk","sdk-go"],"created_at":"2024-10-10T16:06:06.295Z","updated_at":"2025-04-08T13:49:21.957Z","avatar_url":"https://github.com/cludden.png","language":"Go","readme":"# concourse-go-sdk\n[![Go Reference](https://pkg.go.dev/badge/github.com/cludden/concourse-go-sdk.svg)](https://pkg.go.dev/github.com/cludden/concourse-go-sdk)  \n\na minimal SDK for implementing an idiomatic [Concourse](https://concourse-ci.org) [custom resource type](https://concourse-ci.org/implementing-resource-types.html) in go.\n\n\n\n## Getting Started\n1. Define 4 [required types](#required-types) as structs with appropriate json struct tags\n2. Provide a [resource implementation](#resource-implementation) that leverages the types defined in step 1\n3. Define a `func main() {}` that invokes this sdk's `Main` function with your resource and type definitions\n4. Build a `check`, `in`, and `out` binary using [goreleaser](example/.goreleaser.yaml) or directly passing the appropriate linker flags to configure the build variable (e.g. `-ldflags=\"-X 'github.com/cludden/concourse-go-sdk.Operation={check,in,out}'\"`)\n\n*Example*\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"errors\"\n\n\tsdk \"github.com/cludden/concourse-go-sdk\"\n)\n\n// 3. Invoke the Main function provided by this sdk\nfunc main() {\n\tsdk.Main[Source, Version, GetParams, PutParams](\u0026Resource{})\n}\n\n// 1. Define required type definitions\ntype (\n\tGetParams struct{}\n\n\tPutParams struct{}\n\n\tSource struct{}\n\n\tVersion struct{}\n)\n\n// 2. Define resource type and corresponding methods\ntype Resource struct{\n    // embed BaseResource to inherit noop implementations of all optional methods\n    sdk.BaseResource[Source, Version, GetParams, PutParams]\n}\n\n// Check checks for new versions\nfunc (r *Resource) Check(ctx context.Context, s *Source, v *Version) ([]Version, error) {\n\treturn nil, errors.New(\"not implemented\")\n}\n\n// In retrieves the specified version and writes it to the filesystem\nfunc (r *Resource) In(ctx context.Context, s *Source, v *Version, dir string, p *GetParams) ([]sdk.Metadata, error) {\n\treturn nil, errors.New(\"not implemented\")\n}\n\n// Out creates a new version\nfunc (r *Resource) Out(ctx context.Context, s *Source, dir string, p *PutParams) (Version, []sdk.Metadata, error) {\n\treturn Version{}, nil, errors.New(\"not implemented\")\n}\n```\n\n\n\n## Required Types\nThe various resource methods leverage a combination of 4 required types ([Source](#source), [Version](#version), [GetParams](#getparams), [PutParams](#putparams)), which should be implemented as [Go struct types](https://gobyexample.com/structs) with appropriate [struct tags](https://gobyexample.com/json) defined for accurate JSON decoding. Note that the names of these types are not important, but their position in the various method signatures *is*.\n\n### `Source`\nan arbitrary JSON object which specifies the runtime configuration of the resource, including any credentials. This is passed verbatim from the [resource configuration](https://concourse-ci.org/resources.html#schema.resource.source). For the `git` resource, this would include the repo URI, the branch, and the private key, if necessary.\n\n*Example*\n```go\n// Source describes the available configuration for a git resource\ntype Source struct {\n    URI           string   `json:\"uri\"`\n    Branch        string   `json:\"branch\"`\n    PrivateKey    string   `json:\"private_key\"`\n    Paths         []string `json:\"paths\"`\n    IgnorePaths   []string `json:\"ignore_paths\"`\n    DisableCISkip bool     `json:\"disable_ci_skip\"`\n}\n```\n\n### `Version`\na JSON object with string fields, used to uniquely identify an instance of the resource. For `git` this would be the commit's SHA.\n\n*Example*\n```go\n// Version describes the attributes that uniquely identify a git resource version\ntype Version struct {\n    Ref string `json:\"ref\"`\n}\n```\n\n### `GetParams`\nan arbitrary JSON object passed along verbatim from [get step params](https://concourse-ci.org/get-step.html#schema.get.params) on a get step.\n\n*Example*\n```go\n// GetParams describes the available parameters for a git resource get step\ntype GetParams struct {\n    Depth      int      `json:\"depth\"`\n    FetchTags  bool     `json:\"fetch_tags\"`\n    Submodules []string `json:\"submodules\"`\n}\n```\n\n### `PutParams`\nan arbitrary JSON object passed along verbatim from [put step params](https://concourse-ci.org/put-step.html#schema.put.params) on a put step.\n\n*Example*\n```go\n// PutParams describes the available parameters for a git resource put step\ntype PutParams struct {\n    Repository string `json:\"repository\"`\n    Rebase     bool   `json:\"rebase\"`\n    Merge      bool   `json:\"merge\"`\n    Tag        string `json:\"tag\"`\n    Force      bool   `json:\"force\"`\n}\n```\n\n### Validation\nAny of the above types can optionally choose to implement the `Validatable` interface shown below, in which case the sdk will perform runtime validation prior to invoking action methods.\n\n```go\ntype Validatable interface {\n    Validate(context.Context) error\n}\n```\n\n\n\n## Resource Implementation\nA `Resource` can be any struct that satisfies the following interface utilizing the [required types](#required-types) documented above. This package provides a `BaseResource` type that provides an embeddable `Resource` implementation with noops for all methods, allowing consumers to only provide implementations for desired functionality.\n\n```go\n// Resource describes a Concourse custom resource implementation\ntype Resource[Source any, Version any, GetParams any, PutParams any] interface {\n    // Archive intializes an Archive implementation for persisting resource\n    // version history outside of Concourse\n    Archive(context.Context, *Source) (Archive, error)\n\n    // Check checks for new versions\n    Check(context.Context, *Source, *Version) ([]Version, error)\n\n    // Close is called after any Check/In/Out operation\n    Close(context.Context) error\n\n    // In fetches the specified version and writes it to the filesystem\n    In(context.Context, *Source, *Version, string, *GetParams) ([]Metadata, error)\n\n    // Initialize is called prior to any Check/In/Out operation and provides\n    // an opportunity to perform common resource initialization logic\n    Initialize(context.Context, *Source) error\n\n    // Out creates a new resource version\n    Out(context.Context, *Source, string, *PutParams) (Version, []Metadata, error)\n}\n```\n\n*Example*\n```go\ntype (\n\tGetParams struct{}\n\n\tPutParams struct{}\n\n\tSource struct{}\n\n\tVersion struct{\n        Ref string `json:\"ref\"`\n    }\n)\n\ntype MyResource struct {\n\tsdk.BaseResource[Source, Version, GetParams, PutParams]\n}\n\nfunc (r *MyResource) Out(ctx context.Context, source *Source, path string, p *PutParams) (Version, []sdk.Metadata, error) {\n\treturn Version{Ref: \"foo\"}, []sdk.Metadata{{Name: \"bar\", Value: \"baz\"}}, nil\n}\n\n```\n\n\n\n## Archiving\nIn certain situations, Concourse can reset a particular resource's version history (e.g. when the source parameters change). Often times, this is undesirable. This sdk supports archiving resource version history as a workaround. To enable this functionality, a resource should implement an [Archive](#archive) method that initializes and returns a valid archive:\n\n```go\ntype Archive interface {\n    // Close should handle any graceful termination steps (e.g. closing open connections or file handles, persisting local data to a remote store, etc)\n\tClose(ctx context.Context) error\n    // History returns an ordered list of json serialized versions\n\tHistory(ctx context.Context) ([][]byte, error)\n    // Put appends an ordered list of versions to a resource's history, making sure to avoid duplicates\n\tPut(ctx context.Context, versions ...[]byte) error\n}\n```\n\nThis sdk also provides the following out-of-the-box archive implementations that can be utilized via:\n\n```go\nimport (\n    \"github.com/cludden/concourse-go-sdk/pkg/archive\"\n)\n\ntype Source struct {\n    Archive *archive.Config `json:\"archive\"`\n}\n\nfunc (r *Resource) Archive(ctx context.Context, s *Source) (archive.Archive, error) {\n    if s != nil \u0026\u0026 s.Archive != nil {\n        return archive.New(ctx, *s.Archive)\n    }\n    return nil, nil\n}\n```\n\n### `boltdb`\nan archive implementation that utilizes [boltdb](https://pkg.go.dev/github.com/boltdb/bolt) backed by [AWS S3](https://aws.amazon.com/s3/).\n\n\n\n## License\nLicensed under the [MIT License](LICENSE.md)  \nCopyright (c) 2023 Chris Ludden","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcludden%2Fconcourse-go-sdk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcludden%2Fconcourse-go-sdk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcludden%2Fconcourse-go-sdk/lists"}