Skip to content

feat: add awsenv/secretsmanager package for Secrets Manager support #minor#47

Merged
svvitale merged 40 commits into
masterfrom
add-secretsmanager-support
Jul 7, 2026
Merged

feat: add awsenv/secretsmanager package for Secrets Manager support #minor#47
svvitale merged 40 commits into
masterfrom
add-secretsmanager-support

Conversation

@svvitale

@svvitale svvitale commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds a new awsenv/secretsmanager subpackage implementing awsenv.ParamsGetter
backed by AWS Secrets Manager (aws-sdk-go-v2). Mirrors the existing awsenv/v2
SSM adapter pattern.

  • NewParamsGetter(client SecretsManagerAPI) awsenv.ParamsGetter — returns the
    interface directly, consistent with awsenv/v2
  • MustReplaceEnv() — zero-config entry point, matches awsenv/v2 signature
    exactly (no args, uses awsenv.DefaultPrefix and context.Background())
  • GetParams fetches secrets concurrently via errgroup; binary secrets
    (nil SecretString) return an error
  • SecretsManagerAPI interface requires only GetSecretValue, enabling mock
    injection in tests
  • Extracts mustReplaceEnvWithGetter helper in both awsenv/secretsmanager
    and awsenv/v2 to enable unit testing of MustReplaceEnv without live AWS

Usage

import (
    "github.com/sendgrid/aws-env/awsenv/secretsmanager"
)

// Zero-config (uses awsenv.DefaultPrefix = "awsenv:")
secretsmanager.MustReplaceEnv()

// Custom prefix via manual wiring
import (
    awsV2Config "github.com/aws/aws-sdk-go-v2/config"
    awssm "github.com/aws/aws-sdk-go-v2/service/secretsmanager"
    "github.com/sendgrid/aws-env/awsenv"
    "github.com/sendgrid/aws-env/awsenv/secretsmanager"
)

awsCfg, _ := awsV2Config.LoadDefaultConfig(ctx)
replacer := awsenv.NewReplacer("awssecret:", secretsmanager.NewParamsGetter(awssm.NewFromConfig(awsCfg)))
replacer.ReplaceAll(ctx)

Test plan

  • 7/7 table-driven tests for GetParams pass with -race -count=1
    (single secret, multiple secrets, empty slice, nil slice, duplicate names,
    client error, nil SecretString)
  • 3/3 tests for MustReplaceEnv via mustReplaceEnvWithGetter
    (replace, panic-on-error, no-op)
  • 3/3 tests for awsenv/v2 MustReplaceEnv via mustReplaceEnvWithGetter
  • Full ./... suite passes with no regressions

🤖 Generated with Claude Code

svvitale and others added 5 commits June 22, 2026 14:23
Adds a new ParamsGetter implementation backed by AWS Secrets Manager
(aws-sdk-go-v2). Each parameter name is treated as a secret ID and
fetched concurrently via GetSecretValue. Mirrors the awsenv/v2 SSM
adapter pattern.
- Rename awsenv/smv2 → awsenv/secretsmanager
- Return awsenv.ParamsGetter from NewParamsGetter (H1)
- Add nil SecretString test case (H2)
- Add MustReplaceEnv convenience function (M1)
- Add package doc comment (M2)
- Strengthen error assertions with ErrorContains (M3)
- Add nil and duplicate-key test cases (M4)
- Remove loop variable re-declaration dead code (S1)
- Simplify to []*string instead of []result (S2)
- Rename test function to TestGetter_GetParams (S3)
- Document binary secret limitation in GetParams godoc (S4)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Takes no arguments, uses context.Background() and awsenv.DefaultPrefix,
matching the v2 SSM package's convention exactly.
Extract mustReplaceEnvWithGetter helper to enable mock injection,
then test replace, panic-on-error, and no-op behaviors.
@svvitale svvitale changed the title feat: add awsenv/smv2 package for Secrets Manager support feat: add awsenv/secretsmanager package for Secrets Manager support Jun 22, 2026
@svvitale svvitale changed the title feat: add awsenv/secretsmanager package for Secrets Manager support feat: add awsenv/secretsmanager package for Secrets Manager support #minor Jun 22, 2026
svvitale and others added 11 commits June 22, 2026 16:44
- Export ssmGetParametersAPI → SSMGetParametersAPI in awsenv/v2
- Add .mockery.yaml configuring SecretsManagerAPI and SSMGetParametersAPI
- Generate mocks with mockery v3 (with-expecter: true)
- Rewrite secretsmanager and v2 tests to use generated mocks
- Add go:generate directives and make mocks target
- Unexport SecretsManagerAPI → secretsManagerAPI and
  SSMGetParametersAPI → ssmGetParametersAPI; both were only ever
  needed internally for mock injection in tests
- Drop explicit dir/pkgname/filename config from .mockery.yaml;
  mockery v3 defaults place generated mocks in mocks_test.go in the
  source package, making them test-only and invisible to importers
- Remove mocks/ subdirectories; regenerated mocks land in-package
- Convert secretsmanager_test.go from external to internal package
  to access the in-package mock

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Runs mockery automatically when .mockery.yaml or either interface-bearing
source file changes. If the generated mocks_test.go files drift, the hook
rewrites them and fails the commit so the developer can review and re-stage.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- README: expand "Use as a Go library" into a proper section with a
  comparison table and examples for all three backends (v1 SSM, v2 SSM,
  Secrets Manager), each showing both zero-config MustReplaceEnv and
  explicit NewParamsGetter wiring
- secretsmanager godoc: expand package comment with runnable examples
  covering the default and custom-config cases

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
docs/ contains local agent handoff artifacts that should not be
version-controlled. Remove the tracked file and ignore the whole
directory rather than just docs/reviews/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add TestGetParams covering single param, multiple params, empty
  request, client error, missing param (SSM silent omission), and
  WithDecryption flag assertion
- Add TestGetParamsLimit asserting the SSM batch limit of 10
- Revert .gitignore to master state — docs/ ignore was a local artifact

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Configure package registries to use internal Artifactory proxy,
update plugin versions, and rewrite base images (inc-18715).
Queue routing is configured in Buildkite UI pipeline settings.

- Dockerfile: replace golang:${GO_VERSION} with pinned ECR-mirrored
  golang:1.24; replace bare alpine with alpine:3.21.7 ECR mirror;
  activate vendoring (COPY vendor/ + go build -mod=vendor) to avoid
  proxy.golang.org at image build time
- Makefile: rewrite all docker run image refs to ECR mirror paths;
  forward GOPROXY/GOPRIVATE into go test container; replace curl|sh
  golangci-lint install with go install via Artifactory Go proxy;
  stub coverage report step (docker.sendgrid.net/sendgrid/ghi not
  yet mirrored to ECR)
- pipeline.yml: add GOPROXY/GOPRIVATE env; hoist chronicle plugin
  version to in-repo PLUGIN_VERSION_CHRONICLE constant (v1.2.0)
- .gitignore: ignore .jfrog/ audit config directory

ECR image import PR for buildkite/github-release:
  twilio-internal/ecr-image-import#1460

TODO: re-enable make report once docker.sendgrid.net/sendgrid/ghi
is available via ECR mirror or replaced with an alternative.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…otation

Mirrors the bin/coverage approach from acorn-api: generates coverage.html,
coverage.txt, and a graded coverage.annotation; posts the annotation via
buildkite-agent annotate in the report target.
- Close missing backtick fence after Secrets Manager explicit-config example
- Align Makefile test target to -mod=vendor (consistent with bin/coverage and Dockerfile)
- Lint target: replace hard-coded GOPROXY URL with pass-through -e GOPROXY
- Lint target: add missing -e GOPRIVATE pass-through

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
svvitale and others added 11 commits June 23, 2026 13:21
Use golang-testing image for test/lint and golang-alpine for Docker
build stage to fix broken builds on locked-down agents.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace `RUN make build` with the go build command directly so the
alpine-based builder image doesn't need make installed. Remove the
now-unused local `build` Makefile target.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
v1.55.0 fails to compile against Go 1.26 due to an incompatible
x/tools dependency. Switch lint to run the golangci-lint Docker image
directly from ECR instead of go install-ing into the golang image.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Matches the pinned image used in sendgrid/email-accounts-platform.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace deprecated io/ioutil with os package in file_replacer.go and test
- Fix useless self-assert in TestFileReplacer_ReplaceAll_noop
- Add nolint:gosec on test fakeEnv maps (G101 false positives)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@svvitale
svvitale merged commit 9995443 into master Jul 7, 2026
9 checks passed
@svvitale
svvitale deleted the add-secretsmanager-support branch July 7, 2026 20:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants