Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 6 additions & 10 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,16 +1,12 @@
version: 2
updates:
# Go modules. Several dependencies are deliberately held at their newest
# go1.18-compatible release. Reject Dependabot PRs that move them until
# the go directive is raised:
# Go modules. Nothing is held back any more: the go directive is 1.25.0,
# which is what x/net, x/text and gomega each require, so Dependabot PRs
# for them can be taken on their merits.
#
# golang.org/x/net v0.35.0 - newer requires go 1.23
# golang.org/x/text v0.22.0 - newer requires go 1.23
# github.com/onsi/gomega v1.27.10 - newer requires go 1.25
#
# gomega is the trap: it is a direct requirement, so Dependabot proposes
# major jumps that look routine. v1.42.1 declares `go 1.25.0` and would
# silently break the declared 1.18 floor.
# A dependency that raises its own go directive above this floor is still
# a breaking change for consumers, so check the `go` line in any proposed
# bump before merging it.
- package-ecosystem: gomod
directory: "/"
schedule:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ permissions:
contents: read

jobs:
# Keeps the declared go 1.18 floor honest. Compile only: this leg runs an
# Keeps the declared go 1.25 floor honest. Compile only: this leg runs an
# old toolchain deliberately, so no test, lint, or vulnerability scan runs
# here — they would report that toolchain's stdlib advisories, which say
# nothing about this code.
Expand All @@ -24,7 +24,7 @@ jobs:
persist-credentials: false
- uses: actions/setup-go@v7
with:
go-version: "1.18"
go-version: "1.25"
- run: go build ./...

test:
Expand Down
17 changes: 3 additions & 14 deletions .modrotignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,7 @@
# Every entry needs a reason and a condition for removing it again. This
# list is not a way to silence the gate; it exists so the gate stays
# meaningful for dependencies we can actually act on.

# gopkg.in/yaml.v3 — go-yaml/yaml, archived 2025-04-01.
#
# Indirect and test-only: the sole path to it is
# github.com/onsi/gomega/matchers, so it is never part of a consumer's
# build of this library. Nothing imports it from non-test code here.
#
# Not removable by upgrading: every published gomega release, current
# ones included, requires gopkg.in/yaml.v3, so raising the go directive
# would not drop it either. Only dropping gomega from the test suite
# would, which is a larger change than a dependency release should make.
#
# Revisit if gomega ever drops the dependency, or if the test suite
# moves off gomega.
gopkg.in/yaml.v3
# Currently empty. gopkg.in/yaml.v3 was exempted here while gomega
# required it; gomega v1.42.1 moved to the maintained go.yaml.in/yaml/v3
# fork, which is the removal condition that entry recorded.
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ GH_ASSETS :=

SECURITY_SCANS := govulncheck gosec gitleaks

FUZZTIME ?= 30s

# Release notes come from the changelog.d fragments: `make tag` embeds the
# assembled notes in the annotated tag body and `make publish` reads them
# back with --notes-from-tag. Nothing is hand-edited at release time.
Expand Down Expand Up @@ -39,6 +41,13 @@ test: ## Run tests
test-race: ## Run tests with the race detector
go test -race ./...

# `make test` already runs the seed corpus, as Go fuzz targets double as
# ordinary tests. This target is for actually searching: raise FUZZTIME
# when chasing something.
.PHONY: fuzz
fuzz: ## Fuzz the VCAP_APPLICATION/VCAP_SERVICES parser (FUZZTIME=30s)
go test -run '^$$' -fuzz FuzzNew -fuzztime $(FUZZTIME) .

.PHONY: cover
cover: ## Run tests and report coverage
go test -coverprofile=coverage.out ./...
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

### Requirements

Go 1.18 or later.
Go 1.25 or later.

### Usage

Expand Down
2 changes: 0 additions & 2 deletions changelog.d/0001-file-based-bindings.md

This file was deleted.

10 changes: 10 additions & 0 deletions changelog.d/0001-raise-go-floor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[Breaking Changes]
- The minimum Go version is now **1.25** (was 1.18). Consumers on an older toolchain must stay on v1.22.0. The old floor had become what blocked dependency maintenance: every current release of `golang.org/x/net`, `golang.org/x/text` and `gomega` declares a directive above it. (#38)

[Security Updates]
- `golang.org/x/net` and `golang.org/x/text` moved to current releases, clearing the 16 known vulnerabilities their pinned versions carried between them (15 in `x/net` v0.35.0, 1 in `x/text` v0.22.0). None were reachable from this package's code, so `govulncheck` was always green — but scanners that report on presence rather than reachability were not, and consumers run those. (#38)

[Chores]
- `gomega` moved to v1.42.1, which depends on the maintained `go.yaml.in/yaml/v3` instead of the archived `gopkg.in/yaml.v3`. The `.modrotignore` exemption that covered the archived module recorded exactly this as its removal condition, and is now gone — the archived-dependency gate runs with no exemptions at all.
- The `copyloopvar` and `intrange` linters now run. They were already enabled in `.golangci.yml` but golangci-lint disabled them at runtime for being newer than the project's go directive.
- Added `make fuzz`, a fuzz target over the `VCAP_APPLICATION` and `VCAP_SERVICES` parsing that `New` performs. Both documents come from the platform rather than the app, so they are the package's untrusted boundary. (#39)
59 changes: 59 additions & 0 deletions fuzz_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cfenv_test

import (
"testing"

cfenv "github.com/cloudfoundry-community/go-cfenv"
)

// FuzzNew exercises the two documents New parses. Their contents originate
// with the platform and the service brokers bound to an app, not with the
// app itself, so this package is the boundary that has to survive whatever
// arrives. New is expected to return an app or an error for any input, and
// never to panic.
func FuzzNew(f *testing.F) {
f.Add(`{}`, `{}`)
f.Add(
`{"instance_id":"abc","name":"app","limits":{"mem":512,"disk":1024,"fds":16384}}`,
`{"redis":[{"name":"r","label":"redis","tags":["t"],"plan":"free","credentials":{"port":"6379","ports":{"6379/tcp":"32843"}}}]}`,
)
f.Add(`{}`, `{"user-provided":[{"name":"ups","syslog_drain_url":"syslog://x:514","credentials":{"a":{"b":{"c":1}}}}]}`)
f.Add(`{}`, `{"nfs":[{"volume_mounts":[{"container_dir":"/d","mode":"rw"}]}]}`)
f.Add(`{"limits":null}`, `{"x":[]}`)
f.Add(``, ``)

f.Fuzz(func(t *testing.T, application, services string) {
app, err := cfenv.New(map[string]string{
"VCAP_APPLICATION": application,
"VCAP_SERVICES": services,
})
if err != nil {
if app != nil {
t.Fatalf("returned both an app and an error: %v", err)
}

return
}

if app == nil {
t.Fatal("returned neither an app nor an error")
}

// Whatever decoded, the accessors have to stay total: they may find
// nothing, but they must not panic on any shape that got this far.
for _, instances := range app.Services {
for i := range instances {
service := instances[i]
service.CredentialString("uri")
service.Credential("a", "b", "c")
service.CredentialPath("a.b.c")
}
}

app.Services.WithTag("t")
app.Services.WithLabel("redis")
app.Services.WithName("r")
app.Services.WithNameUsingPattern("r.*")
app.Services.WithTagUsingPattern("t.*")
})
}
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
module github.com/cloudfoundry-community/go-cfenv

go 1.18
go 1.25.0

require (
github.com/go-viper/mapstructure/v2 v2.5.0
github.com/onsi/gomega v1.27.10
github.com/onsi/gomega v1.42.1
github.com/sclevine/spec v1.4.0
)

require (
github.com/google/go-cmp v0.5.9 // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/text v0.22.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
github.com/google/go-cmp v0.7.0 // indirect
go.yaml.in/yaml/v3 v3.0.5 // indirect
golang.org/x/net v0.57.0 // indirect
golang.org/x/text v0.40.0 // indirect
)
28 changes: 10 additions & 18 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,22 +1,14 @@
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
github.com/go-viper/mapstructure/v2 v2.5.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/onsi/gomega v1.42.1 h1:iN1rCUX+44NZ1Dc97MPoeFYbFR0vh8zxoxMFwKdyZ6I=
github.com/onsi/gomega v1.42.1/go.mod h1:REff/hsDsodHoKlWsP2mAPhu1+5/6hVYNf9rIEBpeSg=
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
go.yaml.in/yaml/v3 v3.0.5 h1:N6y/pJk8buWs9NY5ERU2HSMfm+IuD/OtfdAnq6kESPw=
go.yaml.in/yaml/v3 v3.0.5/go.mod h1:HVTZu1O7/Vkt2N+BFy8Zza+lnLsABggaTM2ZpNIGuKg=
golang.org/x/net v0.57.0 h1:K5+3DljvIuDG9/Jv9rvyMywYNFCQ9RSUY6OOTTkT+tE=
golang.org/x/net v0.57.0/go.mod h1:KpXc8iv+r3XplLAG/f7Jsf9RPszJzdR0f58q9vGOuEU=
golang.org/x/text v0.40.0 h1:Ub2Z6/xjgF1WrYQz2nuITOEegKFtiIy+rieRJ5lHZKs=
golang.org/x/text v0.40.0/go.mod h1:hpnzDAfGV753zIKo+wk3u1bVKCGPbrnF7+7LBF/UHVY=