diff --git a/util/update-manifest-releases/go.mod b/util/update-manifest-releases/go.mod index 9fbf1c590..9f3e5415f 100644 --- a/util/update-manifest-releases/go.mod +++ b/util/update-manifest-releases/go.mod @@ -3,7 +3,7 @@ module github.com/cloudfoundry/runtime-ci/util/update-manifest-releases go 1.25.0 require ( - github.com/onsi/ginkgo/v2 v2.28.3 + github.com/onsi/ginkgo/v2 v2.31.0 github.com/onsi/gomega v1.41.0 gopkg.in/yaml.v2 v2.4.0 ) diff --git a/util/update-manifest-releases/go.sum b/util/update-manifest-releases/go.sum index ee23ee032..5dbf61b52 100644 --- a/util/update-manifest-releases/go.sum +++ b/util/update-manifest-releases/go.sum @@ -31,8 +31,8 @@ github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo= github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg= github.com/mfridman/tparse v0.18.0 h1:wh6dzOKaIwkUGyKgOntDW4liXSo37qg5AXbIhkMV3vE= github.com/mfridman/tparse v0.18.0/go.mod h1:gEvqZTuCgEhPbYk/2lS3Kcxg1GmTxxU7kTC8DvP0i/A= -github.com/onsi/ginkgo/v2 v2.28.3 h1:4JvMdwtFU0imd8fHx25OJXoDMRexnf8v5NHKYSTTji4= -github.com/onsi/ginkgo/v2 v2.28.3/go.mod h1:+aXOY+vzZ5mu2iI2HpTZUPmM//oQfsNFX6gU9kNcA44= +github.com/onsi/ginkgo/v2 v2.31.0 h1:GtuJos5DFUV9EerYJo8RhYxosYNGvOdDE5haKq6Grfs= +github.com/onsi/ginkgo/v2 v2.31.0/go.mod h1:+aXOY+vzZ5mu2iI2HpTZUPmM//oQfsNFX6gU9kNcA44= github.com/onsi/gomega v1.41.0 h1:OwKp4pXNgVxf6sCplzYo794OFNuoL2q2SBMU5NSWOjA= github.com/onsi/gomega v1.41.0/go.mod h1:M/Uqpu/8qTjtzCLUA2zJHX9Iilrau25x1PdoSRbWh5A= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= diff --git a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/.gitignore b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/.gitignore index 6faaaf315..c9f054620 100644 --- a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/.gitignore +++ b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/.gitignore @@ -1,6 +1,7 @@ .DS_Store TODO tmp/**/* +integration/tmp_*/ *.coverprofile .vscode .idea/ diff --git a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md index d382b0640..fe25998c6 100644 --- a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md +++ b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/CHANGELOG.md @@ -1,3 +1,29 @@ +## 2.31.0 + +Add a bunch of Claude Skills via the marketplace: + +``` +/plugin marketplace add onsi/ginkgo +/plugin install ginkgo@ginkgo +``` + +## 2.30.0 + +### Features +Ginkgo now allows `extentions/global.Reset` to support running multiple suites from within a single process. This may take some massaging on your part (see [1672](https://github.com/onsi/ginkgo/issues/1672)) but can dramatically speed up codebases with O(hundreds) of test suites. + +Thanks @lawrencejones ! + +### Fixes + +- Fix nested --github-output group for progress report nested inside timeline [4f62d7a] + +## 2.29.0 + +`GinkgoHelperGo` makes it easier to write test helpers that need to run in goroutines. Specifically, it makes managing the failure state and capturing failure panics correctly straightforward. + +`ginkgo outline` now includes entries defined in `DescribeTableSubtree` + ## 2.28.3 ### Maintenance diff --git a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/README.md b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/README.md index 6d36e377e..ad5e45f67 100644 --- a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/README.md +++ b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/README.md @@ -106,6 +106,19 @@ And that's just Ginkgo! [Gomega](https://onsi.github.io/gomega/) brings a rich, Happy Testing! +## Using Ginkgo with Claude Code + +Ginkgo ships a set of [Claude Code](https://claude.com/claude-code) skills as a plugin, with this repo doubling as the marketplace, so an agent writing specs in *your* project has Ginkgo's idioms, decorators, and gotchas on hand. From inside Claude Code: + +``` +/plugin marketplace add onsi/ginkgo +/plugin install ginkgo@ginkgo +``` + +(or non-interactively: `claude plugin marketplace add onsi/ginkgo` then `claude plugin install ginkgo@ginkgo`) + +This installs a family of `ginkgo:*` skills that activate automatically while you write and run specs. Start with `ginkgo:overview`; see the [plugin README](plugins/ginkgo/README.md) for the full list. + ## License Ginkgo is MIT-Licensed diff --git a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/core_dsl.go b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/core_dsl.go index 1c5a39a1f..fb5761c1f 100644 --- a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/core_dsl.go +++ b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/core_dsl.go @@ -39,7 +39,6 @@ var flagSet types.GinkgoFlagSet var deprecationTracker = types.NewDeprecationTracker() var suiteConfig = types.NewDefaultSuiteConfig() var reporterConfig = types.NewDefaultReporterConfig() -var suiteDidRun = false var outputInterceptor internal.OutputInterceptor var client parallel_support.Client @@ -259,10 +258,10 @@ for more on how specs are parallelized in Ginkgo. You can also pass suite-level Label() decorators to RunSpecs. The passed-in labels will apply to all specs in the suite. */ func RunSpecs(t GinkgoTestingT, description string, args ...any) bool { - if suiteDidRun { + if global.SuiteDidRun { exitIfErr(types.GinkgoErrors.RerunningSuite()) } - suiteDidRun = true + global.SuiteDidRun = true err := global.PushClone() if err != nil { exitIfErr(err) diff --git a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go index 5d8d00bb1..c380bbf21 100644 --- a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go +++ b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/ginkgo.go @@ -163,17 +163,17 @@ func ginkgoNodeFromCallExpr(fset *token.FileSet, ce *ast.CallExpr, ginkgoPackage n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt) n.Labels = labelFromCallExpr(ce) return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName - case "Context", "Describe", "When", "DescribeTable": + case "Context", "Describe", "When", "DescribeTable", "DescribeTableSubtree": n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt) n.Labels = labelFromCallExpr(ce) n.Pending = pendingFromCallExpr(ce) return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName - case "FContext", "FDescribe", "FWhen", "FDescribeTable": + case "FContext", "FDescribe", "FWhen", "FDescribeTable", "FDescribeTableSubtree": n.Focused = true n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt) n.Labels = labelFromCallExpr(ce) return &n, ginkgoPackageName != nil && *ginkgoPackageName == packageName - case "PContext", "PDescribe", "PWhen", "XContext", "XDescribe", "XWhen", "PDescribeTable", "XDescribeTable": + case "PContext", "PDescribe", "PWhen", "XContext", "XDescribe", "XWhen", "PDescribeTable", "XDescribeTable", "PDescribeTableSubtree", "XDescribeTableSubtree": n.Pending = true n.Text = textOrAltFromCallExpr(ce, undefinedTextAlt) n.Labels = labelFromCallExpr(ce) diff --git a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/outline.go b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/outline.go index e99d557d1..206043f1d 100644 --- a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/outline.go +++ b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/ginkgo/outline/outline.go @@ -54,6 +54,7 @@ func FromASTFile(fset *token.FileSet, src *ast.File) (*outline, error) { // Node is not a Ginkgo spec or container, so it was not pushed onto the stack, continue return true } + expandSubtree(lastVisitedGinkgoNode) stack = stack[0 : len(stack)-1] return true }) @@ -128,3 +129,29 @@ func (o *outline) StringIndent(width int) string { return b.String() } + +// expandSubtree restructures a DescribeTableSubtree node so that each Entry +// child gets a copy of the subtree's spec nodes as its children. This mirrors +// the runtime behavior where each Entry generates a container with the specs +// defined in the DescribeTableSubtree body. +func expandSubtree(gn *ginkgoNode) { + if !strings.Contains(gn.Name, "DescribeTableSubtree") { + return + } + subNodes, entries := splitSubtreeSubnodes(gn.Nodes) + gn.Nodes = entries + for _, entry := range entries { + entry.Nodes = subNodes + } +} + +// splitSubtreeSubnodes splits the child nodes of a DescribeTableSubtree into +// spec/container nodes (defined in the body) and Entry nodes. +func splitSubtreeSubnodes(nodes []*ginkgoNode) ([]*ginkgoNode, []*ginkgoNode) { + for i, node := range nodes { + if strings.Contains(node.Name, "Entry") { + return nodes[:i], nodes[i:] + } + } + return nodes, nil +} diff --git a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/helpergo_dsl.go b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/helpergo_dsl.go new file mode 100644 index 000000000..9d04cc845 --- /dev/null +++ b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/helpergo_dsl.go @@ -0,0 +1,143 @@ +package ginkgo + +import ( + "github.com/onsi/ginkgo/v2/internal/global" + ginkgotypes "github.com/onsi/ginkgo/v2/types" +) + +// GinkgoHelperGo synchronously calls the specified “helper” function in a new +// go routine and with a “defer GinkgoRecover()” already in place, passing the +// function a “helper Fail”. GinkgoHelperGo is typically called from custom test +// helpers that in turn need to synchronously execute caller-supplied custom +// test code in a new Go routine while waiting for this new Go routine to +// terminate (either successfully or failing). +// +// GinkgoHelperGo hides the non-trivial details of correctly unblocking the +// caller's waiting go routine as well as reporting the correct call sites, +// depending on whether the test helper failed, or the caller-supplied function +// had its assertions failing or panicked. +// +// Let's take the following example of a test helper named “EnsureSprockets” +// that runs a set of caller-supplied assertions synchronously on a new Go +// routine and waits for the outcome before returning to the caller of the test +// helper. This is just using Ginkgo: +// +// func EnsureSprockets(sprockets int, assertions func()) { +// GinkgoHelper() +// GinkgoHelperGo(func(helperFail func(string, ...int)) { +// if sprockets == 0 { +// helperFail("sprockets must not be zero") +// } +// assertions() +// }) +// } +// +// And now for an example that additionally uses Gomega assertions. +// +// func EnsureSprockets(sprockets int, assertions func()) { +// GinkgoHelper() +// GinkgoHelperGo(func(helperFail func(string, ...int)) { +// g := gomega.NewGomega(helperFail) +// g.Expect(sprockets).Not(BeZero()) +// assertions() +// }) +// } +// +// The called helper function should make any custom helper-related assertions +// using the passed “helper Fail”. Gomega users will want to create a new Gomega +// wired into this helper Fail. It is expected for the helper function at some +// point to call into a user-supplied function that might contain its own +// assertions. In the example above, that would be the function passed as +// assertions. +// +// Any failing assertion using the helper Gomega in the helper function will be +// reported as a fail at the call site of GinkgoHelperGo. Preferably, only +// custom test helpers call GinkgoHelperGo and thus mark themselves as +// [GinkgoHelper] also: in this case, the fail will be shown at the call site of +// the custom test helper. +// +// Any other failing assertions inside the caller-supplied custom test code and +// thus inside the helper function will instead be reported at the location of +// the failed assertion. +// +// If the caller-supplied custom test code panics, GinkgoHelperGo will fail at +// its call site, or at the call site of the custom test helper if it uses +// GinkgoHelper, reporting the usual stack trace for the panic, as a plain +// GinkgoRecover would also do. +// +// Important: the Gomega passed to the called function must only be used in +// assertions belonging to the test helper, but not any user test code called +// from the test helper. Thus, do not pass the Gomega passed to the helper +// function further on to any user test code functions. +func GinkgoHelperGo(fn func(fail func(message string, callerSkip ...int))) { + // userPanicked signals that the called user code panicked, such as due to a + // failed Gomega assertion. + type userPanicked struct{} + + // helperPanicked signals that some helper code assertion panicked in the + // separate Go routine and we are expected to Fail the current test with that + // reason, but on the caller's Go routine. + type helperPanicked string + + GinkgoHelper() + + // possible types of values sent over the result channel: + // - nil (untyped): no problem at all, proceed. + // - helperPanicked: the message with which to (re)fail in the caller's + // go routine. + // - userPanicked: indication to (also) fail on the caller's go routine; + // the message doesn't matter as the user code fail takes precedence. + ch := make(chan any) + + go func() { + isHelperPanic := false + helperFail := func(message string, callerSkip ...int) { + isHelperPanic = true + Fail(message, callerSkip...) + } + // Please note that we cannot simply recover a helper panic before + // GinkgoRecover kicks in as then GinkgoRecover would always report the + // stack trace only from the place of rethrown panic ... and that's + // pretty useless, because it would just consist of the panic rethrow. + defer func() { + // We need to unblock and immediately fail the waiting caller's + // go routine either for a reason, or just "because" when + // GinkgoRecover has already failed the current test on the + // separate go routine. + if global.Failer.GetState() != ginkgotypes.SpecStatePassed { + if isHelperPanic { + _, failure := global.Failer.Drain() + ch <- helperPanicked(failure.Message) + } else { + // keep the panic failure already recorded by GinkgoRecover. + ch <- userPanicked{} + } + } + close(ch) // causes a nil in case there were no panics anywhere. + }() + // Nota bene: GinkgoRecover always eats any user panic and channel the + // panic value into Ginkgo's Failer.Panic(). We can peek at the last + // failure recorded, which should be nil if GinkgoRecover didn't swallow + // a user code panic. The "problem" with GinkgoRecover is that it turns + // any panic value into a string message, so we loose any specific + // typing. + defer GinkgoRecover() + + fn(helperFail) + }() + + // Did we run into trouble? + switch v := (<-ch).(type) { + case userPanicked: + // The message actually is irrelevant, as it comes only second to + // the already registered user panic message. We just need Fail to + // panic on the caller's go routine in order to unblock the test. + Fail("fn panicked", 1) + case helperPanicked: + // Report the failure on the new go routine instead on the caller's go + // routine. + Fail(string(v), 1) + default: + // It's all fine! + } +} diff --git a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/internal/global/init.go b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/internal/global/init.go index 464e3c97f..14d2552b7 100644 --- a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/internal/global/init.go +++ b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/internal/global/init.go @@ -8,6 +8,12 @@ var Suite *internal.Suite var Failer *internal.Failer var backupSuite *internal.Suite +// SuiteDidRun tracks whether RunSpecs has already been invoked for the current global +// suite. It lives here (rather than in package ginkgo) so that InitializeGlobals can +// clear it, allowing extensions/globals.Reset to support running multiple suites +// sequentially in a single process. +var SuiteDidRun bool + func init() { InitializeGlobals() } @@ -15,6 +21,7 @@ func init() { func InitializeGlobals() { Failer = internal.NewFailer() Suite = internal.NewSuite() + SuiteDidRun = false } func PushClone() error { diff --git a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go index ef66b2289..be5719a8e 100644 --- a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go +++ b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/reporters/default_reporter.go @@ -423,7 +423,7 @@ func (r *DefaultReporter) emitTimeline(indent uint, report types.SpecReport, tim case types.ReportEntry: r.emitReportEntry(indent, x) case types.ProgressReport: - r.emitProgressReport(indent, false, isVeryVerbose, x) + r.emitProgressReport(indent, isVeryVerbose, false, x) case types.SpecEvent: if isVeryVerbose || !x.IsOnlyVisibleAtVeryVerbose() || r.conf.ShowNodeEvents { r.emitSpecEvent(indent, x, isVeryVerbose) @@ -533,6 +533,7 @@ func (r *DefaultReporter) emitProgressReport(indent uint, emitGinkgoWriterOutput indent -= 1 } + // Emit only top-level groups because github logging cannot handle nested groups correctly. if r.conf.GithubOutput && emitGroup { r.emitBlock(r.fi(indent, "::group::Progress Report")) } diff --git a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/types/version.go b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/types/version.go index 4479578f9..1b43092c2 100644 --- a/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/types/version.go +++ b/util/update-manifest-releases/vendor/github.com/onsi/ginkgo/v2/types/version.go @@ -1,3 +1,3 @@ package types -const VERSION = "2.28.3" +const VERSION = "2.31.0" diff --git a/util/update-manifest-releases/vendor/modules.txt b/util/update-manifest-releases/vendor/modules.txt index af131e503..07219d970 100644 --- a/util/update-manifest-releases/vendor/modules.txt +++ b/util/update-manifest-releases/vendor/modules.txt @@ -18,7 +18,7 @@ github.com/google/go-cmp/cmp/internal/value # github.com/google/pprof v0.0.0-20260402051712-545e8a4df936 ## explicit; go 1.24.0 github.com/google/pprof/profile -# github.com/onsi/ginkgo/v2 v2.28.3 +# github.com/onsi/ginkgo/v2 v2.31.0 ## explicit; go 1.25.0 github.com/onsi/ginkgo/v2 github.com/onsi/ginkgo/v2/config