From a2a9a95b283a4d12850e4e7696c10b401d40a69b Mon Sep 17 00:00:00 2001 From: Dmytro Haidashenko <34754799+dhaidashenko@users.noreply.github.com> Date: Fri, 3 Nov 2023 14:20:04 +0100 Subject: [PATCH 01/27] migrate common utils from core/internal/testutils/testutils.go (#214) Co-authored-by: Jordan Krage --- pkg/utils/tests/logs.go | 49 ++++++++++++++++++++++++++++++++++++++++ pkg/utils/tests/tests.go | 21 +++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 pkg/utils/tests/logs.go diff --git a/pkg/utils/tests/logs.go b/pkg/utils/tests/logs.go new file mode 100644 index 0000000000..5d838bb95a --- /dev/null +++ b/pkg/utils/tests/logs.go @@ -0,0 +1,49 @@ +package tests + +import ( + "strings" + "testing" + + "go.uber.org/zap/zaptest/observer" +) + +// AssertLogEventually waits until at least one log message containing the +// specified msg is emitted. +// NOTE: This does not "pop" messages so it cannot be used multiple times to +// check for new instances of the same msg. See AssertLogCountEventually instead. +// +// Get a *observer.ObservedLogs like so: +// +// observedZapCore, observedLogs := observer.New(zap.DebugLevel) +// lggr := logger.TestLogger(t, observedZapCore) +func AssertLogEventually(t *testing.T, observedLogs *observer.ObservedLogs, msg string) { + AssertLogCountEventually(t, observedLogs, msg, 1) +} + +// AssertLogCountEventually waits until at least count log message containing the +// specified msg is emitted +func AssertLogCountEventually(t *testing.T, observedLogs *observer.ObservedLogs, msg string, count int) { + AssertEventually(t, func() bool { + i := 0 + for _, l := range observedLogs.All() { + if strings.Contains(l.Message, msg) { + i++ + if i >= count { + return true + } + } + } + return false + }) +} + +// RequireLogMessage fails the test if emitted logs don't contain the given message +func RequireLogMessage(t *testing.T, observedLogs *observer.ObservedLogs, msg string) { + for _, l := range observedLogs.All() { + if strings.Contains(l.Message, msg) { + return + } + } + t.Log("observed logs", observedLogs.All()) + t.Fatalf("expected observed logs to contain msg %q, but it didn't", msg) +} diff --git a/pkg/utils/tests/tests.go b/pkg/utils/tests/tests.go index f6078d18ee..510a2d7a34 100644 --- a/pkg/utils/tests/tests.go +++ b/pkg/utils/tests/tests.go @@ -4,6 +4,8 @@ import ( "context" "testing" "time" + + "github.com/stretchr/testify/assert" ) func Context(t *testing.T) context.Context { @@ -33,3 +35,22 @@ func WaitTimeout(t *testing.T) time.Duration { } return DefaultWaitTimeout } + +// TestInterval is just a sensible poll interval that gives fast tests without +// risk of spamming +const TestInterval = 100 * time.Millisecond + +// AssertEventually waits for f to return true +func AssertEventually(t *testing.T, f func() bool) { + assert.Eventually(t, f, WaitTimeout(t), TestInterval/2) +} + +// RequireSignal waits for the channel to close (or receive anything) and +// fatals the test if the default wait timeout is exceeded +func RequireSignal(t *testing.T, ch <-chan struct{}, failMsg string) { + select { + case <-ch: + case <-time.After(WaitTimeout(t)): + t.Fatal(failMsg) + } +} From 06f11934809d16c483832287ef89a16c0b0990ca Mon Sep 17 00:00:00 2001 From: engnke Date: Mon, 12 Jan 2026 17:57:21 -0500 Subject: [PATCH 02/27] add nop info lookup token --- pkg/chipingress/auth.go | 6 ++++++ pkg/chipingress/client.go | 34 +++++++++++++++++++++++++--------- pkg/chipingress/client_test.go | 14 ++++++++++++++ 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/pkg/chipingress/auth.go b/pkg/chipingress/auth.go index 04fe85b0c1..3195c37b57 100644 --- a/pkg/chipingress/auth.go +++ b/pkg/chipingress/auth.go @@ -14,6 +14,12 @@ type HeaderProvider interface { Headers(ctx context.Context) (map[string]string, error) } +type HeaderProviderFunc func(ctx context.Context) (map[string]string, error) + +func (f HeaderProviderFunc) Headers(ctx context.Context) (map[string]string, error) { + return f(ctx) +} + // Basic-Auth authentication for Chip Ingress type basicAuthCredentials struct { authHeader map[string]string diff --git a/pkg/chipingress/client.go b/pkg/chipingress/client.go index c6f40297ae..07bb35a490 100644 --- a/pkg/chipingress/client.go +++ b/pkg/chipingress/client.go @@ -44,13 +44,14 @@ type Opt func(*clientConfig) // clientConfig is the configuration for the ChipIngressClient. type clientConfig struct { - transportCredentials credentials.TransportCredentials - perRPCCredentials credentials.PerRPCCredentials - headerProvider HeaderProvider - insecureConnection bool - host string - meterProvider metric.MeterProvider - tracerProvider trace.TracerProvider + transportCredentials credentials.TransportCredentials + perRPCCredentials credentials.PerRPCCredentials + headerProvider HeaderProvider + insecureConnection bool + host string + meterProvider metric.MeterProvider + tracerProvider trace.TracerProvider + nopInfoHeaderProvider HeaderProvider } func newClientConfig(host string) *clientConfig { @@ -59,8 +60,9 @@ func newClientConfig(host string) *clientConfig { perRPCCredentials: nil, host: host, // Default to insecure connection - insecureConnection: true, - transportCredentials: insecure.NewCredentials(), + insecureConnection: true, + transportCredentials: insecure.NewCredentials(), + nopInfoHeaderProvider: nil, } return cfg } @@ -116,6 +118,10 @@ func NewClient(address string, opts ...Opt) (Client, error) { // NOTE: not supporting streaming interceptors } + if cfg.nopInfoHeaderProvider != nil { + grpcOpts = append(grpcOpts, grpc.WithUnaryInterceptor(newHeaderInterceptor(cfg.nopInfoHeaderProvider))) + } + conn, err := grpc.NewClient(address, grpcOpts...) if err != nil { return nil, err @@ -226,6 +232,16 @@ func WithTracerProvider(provider trace.TracerProvider) Opt { return func(c *clientConfig) { c.tracerProvider = provider } } +func WithNOPLookup() Opt { + return func(c *clientConfig) { + c.nopInfoHeaderProvider = HeaderProviderFunc(func(ctx context.Context) (map[string]string, error) { + return map[string]string{ + "x-include-nop-info": "true", + }, nil + }) + } +} + // newHeaderInterceptor creates a unary interceptor that adds headers from a HeaderProvider func newHeaderInterceptor(provider HeaderProvider) grpc.UnaryClientInterceptor { return func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error { diff --git a/pkg/chipingress/client_test.go b/pkg/chipingress/client_test.go index 979bf02cbd..4bd5b9521d 100644 --- a/pkg/chipingress/client_test.go +++ b/pkg/chipingress/client_test.go @@ -568,6 +568,20 @@ func TestOptions(t *testing.T) { WithTokenAuth(mockProvider)(&config) assert.NotNil(t, config.perRPCCredentials) }) + + t.Run("WithNopLookup", func(t *testing.T) { + mockProvider := &mockHeaderProvider{ + headers: map[string]string{"x-include-nop-info": "true"}, + } + config := defaultCfg + WithNOPLookup()(&config) + assert.NotNil(t, config.nopInfoHeaderProvider) + + headers, err := config.nopInfoHeaderProvider.Headers(t.Context()) + assert.NoError(t, err) + assert.Equal(t, mockProvider.headers, headers) + + }) } func TestHeaderInterceptor(t *testing.T) { From 37749810fc2b4891dad22aaec7d9e3c25f1fa1ac Mon Sep 17 00:00:00 2001 From: engnke Date: Tue, 13 Jan 2026 06:18:21 -0500 Subject: [PATCH 03/27] refactoring --- pkg/chipingress/client_test.go | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/pkg/chipingress/client_test.go b/pkg/chipingress/client_test.go index 4bd5b9521d..db2cb9bf16 100644 --- a/pkg/chipingress/client_test.go +++ b/pkg/chipingress/client_test.go @@ -20,11 +20,12 @@ import ( var ( defaultCfg = clientConfig{ - transportCredentials: insecure.NewCredentials(), - insecureConnection: true, // Default to insecure connection - host: "localhost", - perRPCCredentials: nil, // No per-RPC credentials by default - headerProvider: nil, + transportCredentials: insecure.NewCredentials(), + insecureConnection: true, // Default to insecure connection + host: "localhost", + perRPCCredentials: nil, // No per-RPC credentials by default + headerProvider: nil, + nopInfoHeaderProvider: nil, } ) @@ -570,17 +571,13 @@ func TestOptions(t *testing.T) { }) t.Run("WithNopLookup", func(t *testing.T) { - mockProvider := &mockHeaderProvider{ - headers: map[string]string{"x-include-nop-info": "true"}, - } config := defaultCfg WithNOPLookup()(&config) assert.NotNil(t, config.nopInfoHeaderProvider) headers, err := config.nopInfoHeaderProvider.Headers(t.Context()) assert.NoError(t, err) - assert.Equal(t, mockProvider.headers, headers) - + assert.Equal(t, "true", headers["x-include-nop-info"]) }) } From 75cffa94f70d8e85d0c72e80cf6a62c68cdfae5c Mon Sep 17 00:00:00 2001 From: engnke Date: Tue, 13 Jan 2026 10:24:06 -0500 Subject: [PATCH 04/27] make headerfunc unexported --- pkg/chipingress/auth.go | 4 ++-- pkg/chipingress/client.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/chipingress/auth.go b/pkg/chipingress/auth.go index 3195c37b57..e41f54b469 100644 --- a/pkg/chipingress/auth.go +++ b/pkg/chipingress/auth.go @@ -14,9 +14,9 @@ type HeaderProvider interface { Headers(ctx context.Context) (map[string]string, error) } -type HeaderProviderFunc func(ctx context.Context) (map[string]string, error) +type headerProviderFunc func(ctx context.Context) (map[string]string, error) -func (f HeaderProviderFunc) Headers(ctx context.Context) (map[string]string, error) { +func (f headerProviderFunc) Headers(ctx context.Context) (map[string]string, error) { return f(ctx) } diff --git a/pkg/chipingress/client.go b/pkg/chipingress/client.go index 07bb35a490..d22b1807d1 100644 --- a/pkg/chipingress/client.go +++ b/pkg/chipingress/client.go @@ -234,7 +234,7 @@ func WithTracerProvider(provider trace.TracerProvider) Opt { func WithNOPLookup() Opt { return func(c *clientConfig) { - c.nopInfoHeaderProvider = HeaderProviderFunc(func(ctx context.Context) (map[string]string, error) { + c.nopInfoHeaderProvider = headerProviderFunc(func(ctx context.Context) (map[string]string, error) { return map[string]string{ "x-include-nop-info": "true", }, nil From 474114804cae14e89bc6bbd045f499cd7ab5e34f Mon Sep 17 00:00:00 2001 From: engnke Date: Tue, 13 Jan 2026 11:23:25 -0500 Subject: [PATCH 05/27] fix testifylint errors --- pkg/chipingress/client_test.go | 127 +++++++++++++++++---------------- 1 file changed, 64 insertions(+), 63 deletions(-) diff --git a/pkg/chipingress/client_test.go b/pkg/chipingress/client_test.go index db2cb9bf16..53d8ff7731 100644 --- a/pkg/chipingress/client_test.go +++ b/pkg/chipingress/client_test.go @@ -16,6 +16,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/chipingress/mocks" "github.com/smartcontractkit/chainlink-common/pkg/chipingress/pb" + "github.com/stretchr/testify/require" ) var ( @@ -35,7 +36,7 @@ func TestClient(t *testing.T) { // Create new client client, err := NewClient("localhost:8080", WithTransportCredentials(insecure.NewCredentials())) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, client) }) @@ -54,7 +55,7 @@ func TestClient(t *testing.T) { t.Run("valid address with port", func(t *testing.T) { client, err := NewClient("localhost:8080") - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, client) }) @@ -67,11 +68,11 @@ func TestClient(t *testing.T) { // Test Close returns no error err := client.Close() - assert.NoError(t, err) + require.NoError(t, err) // Test Ping returns success pingResp, err := client.Ping(context.Background(), &pb.EmptyRequest{}) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, pingResp) assert.Equal(t, "pong", pingResp.Message) @@ -80,7 +81,7 @@ func TestClient(t *testing.T) { {Subject: "test", Schema: `{"test":"value"}`, Format: 1}, } result, err := client.RegisterSchemas(context.Background(), schemas...) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, result) assert.Empty(t, result) }) @@ -98,14 +99,14 @@ func TestNewEvent(t *testing.T) { "subject": "example-subject", "time": time.Now().Add(-5 * time.Second), } - assert.NoError(t, err) + require.NoError(t, err) event, err := NewEvent("some-domain_here", "platform.on_chain.forwarder.ReportProcessed", protoBytes, attributes) - assert.NoError(t, err) + require.NoError(t, err) // There should be no validation errors err = event.Validate() - assert.NoError(t, err) + require.NoError(t, err) // Assert fields were set as expected assert.Equal(t, "some-domain_here", event.Source()) @@ -121,7 +122,7 @@ func TestNewEvent(t *testing.T) { // Assert the event data was set as expected var resultProto pb.PingResponse err = proto.Unmarshal(event.Data(), &resultProto) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, testProto.Message, resultProto.Message) } @@ -129,15 +130,15 @@ func TestEventToProto(t *testing.T) { // Create a test protobuf message testProto := pb.PingResponse{Message: "test message"} protoBytes, err := proto.Marshal(&testProto) - assert.NoError(t, err) + require.NoError(t, err) t.Run("successful conversion", func(t *testing.T) { // Create a CloudEvent event, err := NewEvent("test-domain", "test.event.type", protoBytes, nil) - assert.NoError(t, err) + require.NoError(t, err) // Convert to proto eventPb, err := EventToProto(event) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, eventPb) // Verify the converted protobuf event has the expected fields @@ -155,12 +156,12 @@ func TestEventToProto(t *testing.T) { } event, err := NewEvent("test-domain", "test.event.type", protoBytes, attributes) - assert.NoError(t, err) + require.NoError(t, err) // Convert to proto eventPb, err := EventToProto(event) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, eventPb) // Verify the converted protobuf event has the expected fields @@ -172,7 +173,7 @@ func TestEventToProto(t *testing.T) { assert.NotNil(t, eventPb.Attributes["dataschema"]) eventFromPb, err := ProtoToEvent(eventPb) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, eventFromPb) // Verify attributes were preserved @@ -184,11 +185,11 @@ func TestEventToProto(t *testing.T) { t.Run("conversion preserves extensions", func(t *testing.T) { // Create event which should have recordedtime extension event, err := NewEvent("test-domain", "test.event.type", protoBytes, nil) - assert.NoError(t, err) + require.NoError(t, err) // Convert to proto eventPb, err := EventToProto(event) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, eventPb) // Verify extensions are present @@ -203,11 +204,11 @@ func TestEventToProto(t *testing.T) { t.Run("conversion with empty data", func(t *testing.T) { // Create event with empty data event, err := NewEvent("test-domain", "test.event.type", []byte{}, nil) - assert.NoError(t, err) + require.NoError(t, err) // Convert to proto eventPb, err := EventToProto(event) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, eventPb) // Verify basic fields are still set @@ -221,21 +222,21 @@ func TestProtoToEvent(t *testing.T) { // Create a test protobuf message testProto := pb.PingResponse{Message: "test message for proto conversion"} protoBytes, err := proto.Marshal(&testProto) - assert.NoError(t, err) + require.NoError(t, err) t.Run("successful conversion from protobuf", func(t *testing.T) { // First create a CloudEvent and convert to proto originalEvent, err := NewEvent("test-domain", "test.event.type", protoBytes, nil) - assert.NoError(t, err) + require.NoError(t, err) // Convert to proto eventPb, err := EventToProto(originalEvent) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, eventPb) // Now test ProtoToEvent conversion back convertedEvent, err := ProtoToEvent(eventPb) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, convertedEvent) // Verify the converted event has the expected fields @@ -247,7 +248,7 @@ func TestProtoToEvent(t *testing.T) { // Verify the data can be unmarshaled back to the original proto var resultProto pb.PingResponse err = proto.Unmarshal(convertedEvent.Data(), &resultProto) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, testProto.Message, resultProto.Message) }) @@ -259,14 +260,14 @@ func TestProtoToEvent(t *testing.T) { } originalEvent, err := NewEvent("test-domain", "test.event.type", protoBytes, attributes) - assert.NoError(t, err) + require.NoError(t, err) // Convert to proto and back eventPb, err := EventToProto(originalEvent) - assert.NoError(t, err) + require.NoError(t, err) convertedEvent, err := ProtoToEvent(eventPb) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, convertedEvent) // Verify all attributes were preserved @@ -283,7 +284,7 @@ func TestProtoToEvent(t *testing.T) { t.Run("conversion with nil protobuf event", func(t *testing.T) { // Test with nil input convertedEvent, err := ProtoToEvent(nil) - assert.Error(t, err) + require.Error(t, err) assert.Equal(t, CloudEvent{}, convertedEvent) assert.Contains(t, err.Error(), "could not convert proto to event") }) @@ -298,25 +299,25 @@ func TestProtoToEvent(t *testing.T) { }, } complexBytes, err := proto.Marshal(complexProto) - assert.NoError(t, err) + require.NoError(t, err) // Create original event originalEvent, err := NewEvent("complex-domain", "complex.event.type", complexBytes, map[string]any{ "subject": "complex-subject", }) - assert.NoError(t, err) + require.NoError(t, err) // Convert to proto and back eventPb, err := EventToProto(originalEvent) - assert.NoError(t, err) + require.NoError(t, err) convertedEvent, err := ProtoToEvent(eventPb) - assert.NoError(t, err) + require.NoError(t, err) // Verify data integrity var resultProto pb.PublishResponse err = proto.Unmarshal(convertedEvent.Data(), &resultProto) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, resultProto.Results, 3) assert.Equal(t, "event-1", resultProto.Results[0].EventId) assert.Equal(t, "event-2", resultProto.Results[1].EventId) @@ -331,14 +332,14 @@ func TestProtoToEvent(t *testing.T) { t.Run("conversion with empty data", func(t *testing.T) { // Create event with empty data originalEvent, err := NewEvent("empty-domain", "empty.event.type", []byte{}, nil) - assert.NoError(t, err) + require.NoError(t, err) // Convert to proto and back eventPb, err := EventToProto(originalEvent) - assert.NoError(t, err) + require.NoError(t, err) convertedEvent, err := ProtoToEvent(eventPb) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, convertedEvent) // Verify basic fields are preserved @@ -353,25 +354,25 @@ func TestEventsToBatch(t *testing.T) { testProto1 := pb.PingResponse{Message: "test message 1"} testProto2 := pb.PingResponse{Message: "test message 2"} protoBytes1, err := proto.Marshal(&testProto1) - assert.NoError(t, err) + require.NoError(t, err) protoBytes2, err := proto.Marshal(&testProto2) - assert.NoError(t, err) + require.NoError(t, err) t.Run("successful batch conversion with multiple events", func(t *testing.T) { // Create multiple CloudEvents event1, err := NewEvent("domain1", "type1", protoBytes1, nil) - assert.NoError(t, err) + require.NoError(t, err) event2, err := NewEvent("domain2", "type2", protoBytes2, map[string]any{ "subject": "test-subject", }) - assert.NoError(t, err) + require.NoError(t, err) events := []CloudEvent{event1, event2} // Convert to batch batch, err := EventsToBatch(events) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, batch) assert.Len(t, batch.Events, 2) @@ -389,12 +390,12 @@ func TestEventsToBatch(t *testing.T) { t.Run("batch conversion with single event", func(t *testing.T) { event, err := NewEvent("single-domain", "single-type", protoBytes1, nil) - assert.NoError(t, err) + require.NoError(t, err) events := []CloudEvent{event} batch, err := EventsToBatch(events) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, batch) assert.Len(t, batch.Events, 1) @@ -408,9 +409,9 @@ func TestEventsToBatch(t *testing.T) { events := []CloudEvent{} batch, err := EventsToBatch(events) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, batch) - assert.Len(t, batch.Events, 0) + assert.Empty(t, batch.Events) }) t.Run("batch conversion preserves event data", func(t *testing.T) { @@ -422,38 +423,38 @@ func TestEventsToBatch(t *testing.T) { }, } complexBytes, err := proto.Marshal(complexProto) - assert.NoError(t, err) + require.NoError(t, err) event1, err := NewEvent("data-domain1", "data-type1", protoBytes1, nil) - assert.NoError(t, err) + require.NoError(t, err) event2, err := NewEvent("data-domain2", "data-type2", complexBytes, nil) - assert.NoError(t, err) + require.NoError(t, err) events := []CloudEvent{event1, event2} batch, err := EventsToBatch(events) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, batch) assert.Len(t, batch.Events, 2) // Convert protobuf events back to CloudEvents to verify data convertedEvent1, err := ProtoToEvent(batch.Events[0]) - assert.NoError(t, err) + require.NoError(t, err) convertedEvent2, err := ProtoToEvent(batch.Events[1]) - assert.NoError(t, err) + require.NoError(t, err) // Verify first event data can be unmarshaled var resultProto1 pb.PingResponse err = proto.Unmarshal(convertedEvent1.Data(), &resultProto1) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, testProto1.Message, resultProto1.Message) // Verify second event data can be unmarshaled var resultProto2 pb.PublishResponse err = proto.Unmarshal(convertedEvent2.Data(), &resultProto2) - assert.NoError(t, err) + require.NoError(t, err) assert.Len(t, resultProto2.Results, 2) assert.Equal(t, "batch-event-1", resultProto2.Results[0].EventId) assert.Equal(t, "batch-event-2", resultProto2.Results[1].EventId) @@ -463,9 +464,9 @@ func TestEventsToBatch(t *testing.T) { var events []CloudEvent batch, err := EventsToBatch(events) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, batch) - assert.Len(t, batch.Events, 0) + assert.Empty(t, batch.Events) }) t.Run("batch conversion preserves all event attributes", func(t *testing.T) { @@ -481,15 +482,15 @@ func TestEventsToBatch(t *testing.T) { } event1, err := NewEvent("attr-domain1", "attr-type1", protoBytes1, attributes1) - assert.NoError(t, err) + require.NoError(t, err) event2, err := NewEvent("attr-domain2", "attr-type2", protoBytes2, attributes2) - assert.NoError(t, err) + require.NoError(t, err) events := []CloudEvent{event1, event2} batch, err := EventsToBatch(events) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, batch) assert.Len(t, batch.Events, 2) @@ -518,12 +519,12 @@ func TestEventsToBatch(t *testing.T) { "subject": fmt.Sprintf("subject-%d", i), }, ) - assert.NoError(t, err) + require.NoError(t, err) events[i] = event } batch, err := EventsToBatch(events) - assert.NoError(t, err) + require.NoError(t, err) assert.NotNil(t, batch) assert.Len(t, batch.Events, numEvents) @@ -576,7 +577,7 @@ func TestOptions(t *testing.T) { assert.NotNil(t, config.nopInfoHeaderProvider) headers, err := config.nopInfoHeaderProvider.Headers(t.Context()) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, "true", headers["x-include-nop-info"]) }) } @@ -603,7 +604,7 @@ func TestHeaderInterceptor(t *testing.T) { // Call the interceptor err := interceptor(t.Context(), "testMethod", nil, nil, nil, mockInvoker) - assert.NoError(t, err) + require.NoError(t, err) // Extract metadata from context and verify headers were added md, ok := metadata.FromOutgoingContext(capturedCtx) @@ -688,7 +689,7 @@ func TestClient_RegisterSchemas(t *testing.T) { } result, err := client.RegisterSchemas(context.Background(), schemas...) - assert.NoError(t, err) + require.NoError(t, err) assert.Equal(t, map[string]int{"schema1": 1, "schema2": 2}, result) }) From 8ebfe749488dca5e415c0860d560711688903b0e Mon Sep 17 00:00:00 2001 From: engnke Date: Tue, 13 Jan 2026 12:42:34 -0500 Subject: [PATCH 06/27] fix import order --- pkg/chipingress/client_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/chipingress/client_test.go b/pkg/chipingress/client_test.go index 53d8ff7731..a4722a2c9b 100644 --- a/pkg/chipingress/client_test.go +++ b/pkg/chipingress/client_test.go @@ -7,7 +7,6 @@ import ( "time" ce "github.com/cloudevents/sdk-go/v2" - "github.com/stretchr/testify/assert" "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" @@ -16,6 +15,7 @@ import ( "github.com/smartcontractkit/chainlink-common/pkg/chipingress/mocks" "github.com/smartcontractkit/chainlink-common/pkg/chipingress/pb" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) From d0a5266a6ed6de7bbed9fb719b32c4ef7bb91454 Mon Sep 17 00:00:00 2001 From: engnke <168561091+engnke@users.noreply.github.com> Date: Wed, 14 Jan 2026 06:21:39 -0500 Subject: [PATCH 07/27] Update pkg/chipingress/client_test.go Co-authored-by: Jordan Krage --- pkg/chipingress/client_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/chipingress/client_test.go b/pkg/chipingress/client_test.go index a4722a2c9b..39838263b2 100644 --- a/pkg/chipingress/client_test.go +++ b/pkg/chipingress/client_test.go @@ -8,15 +8,16 @@ import ( ce "github.com/cloudevents/sdk-go/v2" "google.golang.org/grpc" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/metadata" "google.golang.org/protobuf/proto" - + "github.com/smartcontractkit/chainlink-common/pkg/chipingress/mocks" "github.com/smartcontractkit/chainlink-common/pkg/chipingress/pb" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) var ( From 39941bd1d9faa48adcf0d047f0ff9c5795fe5997 Mon Sep 17 00:00:00 2001 From: Jordan Krage Date: Wed, 14 Jan 2026 08:27:01 -0600 Subject: [PATCH 08/27] Enable continue-on-error for golangci_lint job Allow module linting to continue on errors. --- .github/workflows/golangci_lint.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index e84cbef883..2ac259b0c3 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -22,6 +22,8 @@ jobs: if: ${{ github.event_name != 'merge_group' }} needs: detect-modules runs-on: ubuntu-latest + # Modules are independent + continue-on-error: true strategy: matrix: module: ${{ fromJSON(needs.detect-modules.outputs.modules) }} From d457290773d50d1363702b0544c08e227b2750ea Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:23:52 -0500 Subject: [PATCH 09/27] Use module path for golangci-lint report XML --- .github/workflows/golangci_lint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index 2ac259b0c3..ac7274cf95 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -52,6 +52,7 @@ jobs: checkout-repo: false golangci-lint-version: v${{ steps.get-version.outputs.version }} go-directory: ${{ matrix.module }} + golangci-lint-args: --output.text.path=stdout --output.checkstyle.path=${{ matrix.module }}/golangci-lint-report.xml golangci-lint: # Required sink job that waits for all lint jobs to complete From 36b468dcb5f80cb62bd6ccec6097112c7c73eab6 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:28:39 -0500 Subject: [PATCH 10/27] Add debug step to find path to xml report for golangci-lint --- .github/workflows/golangci_lint.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index ac7274cf95..3c6e5885a9 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -54,6 +54,12 @@ jobs: go-directory: ${{ matrix.module }} golangci-lint-args: --output.text.path=stdout --output.checkstyle.path=${{ matrix.module }}/golangci-lint-report.xml + - name: Debug + if: ${{ always() }} + run: | + echo "Debugging lint results for module ${{ matrix.module }}" + find . -name "golangci-lint-report.xml" + golangci-lint: # Required sink job that waits for all lint jobs to complete if: ${{ github.event_name != 'merge_group' }} From dcb4562a4fe1cdea67c93c9afe8ab64a8b6a47be Mon Sep 17 00:00:00 2001 From: engnke Date: Wed, 14 Jan 2026 10:39:10 -0500 Subject: [PATCH 11/27] refactor for lint --- pkg/chipingress/client_test.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/pkg/chipingress/client_test.go b/pkg/chipingress/client_test.go index 39838263b2..dfd843e800 100644 --- a/pkg/chipingress/client_test.go +++ b/pkg/chipingress/client_test.go @@ -7,15 +7,14 @@ import ( "time" ce "github.com/cloudevents/sdk-go/v2" - "google.golang.org/grpc" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "google.golang.org/grpc" + gp "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/metadata" "google.golang.org/protobuf/proto" - + "github.com/smartcontractkit/chainlink-common/pkg/chipingress/mocks" "github.com/smartcontractkit/chainlink-common/pkg/chipingress/pb" ) @@ -595,7 +594,7 @@ func TestHeaderInterceptor(t *testing.T) { // Create a mock invoker that captures the context var capturedCtx context.Context - mockInvoker := func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, opts ...grpc.CallOption) error { + mockInvoker := func(ctx context.Context, method string, req, reply interface{}, cc *gp.ClientConn, opts ...gp.CallOption) error { capturedCtx = ctx return nil } From 46d22f61819553e233b2bf946e6b13a8fe0d71cf Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:39:28 -0500 Subject: [PATCH 12/27] Show working dir --- .github/workflows/golangci_lint.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index 3c6e5885a9..21b68c94b0 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -58,7 +58,9 @@ jobs: if: ${{ always() }} run: | echo "Debugging lint results for module ${{ matrix.module }}" - find . -name "golangci-lint-report.xml" + echo "Current working directory: $(pwd)" + echo "Looking for golangci-lint-report.xml files:" + find . -name "golangci-lint-report.xml" -type f -exec ls -lh {} \; -exec echo "Contents of {}:" \; -exec cat {} \; golangci-lint: # Required sink job that waits for all lint jobs to complete From 6f5f5fe8dba1d9c2dc8cec49ba3d7218896c0190 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:42:01 -0500 Subject: [PATCH 13/27] Revert "Show working dir" This reverts commit 46d22f61819553e233b2bf946e6b13a8fe0d71cf. --- .github/workflows/golangci_lint.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index 21b68c94b0..3c6e5885a9 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -58,9 +58,7 @@ jobs: if: ${{ always() }} run: | echo "Debugging lint results for module ${{ matrix.module }}" - echo "Current working directory: $(pwd)" - echo "Looking for golangci-lint-report.xml files:" - find . -name "golangci-lint-report.xml" -type f -exec ls -lh {} \; -exec echo "Contents of {}:" \; -exec cat {} \; + find . -name "golangci-lint-report.xml" golangci-lint: # Required sink job that waits for all lint jobs to complete From f0d204fd8c23d3f0e4d4f5d4daf42c6c7c6ce48d Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:42:05 -0500 Subject: [PATCH 14/27] Revert "Add debug step to find path to xml report for golangci-lint" This reverts commit 36b468dcb5f80cb62bd6ccec6097112c7c73eab6. --- .github/workflows/golangci_lint.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index 3c6e5885a9..ac7274cf95 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -54,12 +54,6 @@ jobs: go-directory: ${{ matrix.module }} golangci-lint-args: --output.text.path=stdout --output.checkstyle.path=${{ matrix.module }}/golangci-lint-report.xml - - name: Debug - if: ${{ always() }} - run: | - echo "Debugging lint results for module ${{ matrix.module }}" - find . -name "golangci-lint-report.xml" - golangci-lint: # Required sink job that waits for all lint jobs to complete if: ${{ github.event_name != 'merge_group' }} From ba135e24ec59ce66b1c7d76e0d732255463b4170 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:42:34 -0500 Subject: [PATCH 15/27] Revert "refactor for lint" This reverts commit dcb4562a4fe1cdea67c93c9afe8ab64a8b6a47be. --- pkg/chipingress/client_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/chipingress/client_test.go b/pkg/chipingress/client_test.go index dfd843e800..39838263b2 100644 --- a/pkg/chipingress/client_test.go +++ b/pkg/chipingress/client_test.go @@ -7,14 +7,15 @@ import ( "time" ce "github.com/cloudevents/sdk-go/v2" + "google.golang.org/grpc" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - gp "google.golang.org/grpc" + "google.golang.org/grpc" "google.golang.org/grpc/credentials" "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/metadata" "google.golang.org/protobuf/proto" - + "github.com/smartcontractkit/chainlink-common/pkg/chipingress/mocks" "github.com/smartcontractkit/chainlink-common/pkg/chipingress/pb" ) @@ -594,7 +595,7 @@ func TestHeaderInterceptor(t *testing.T) { // Create a mock invoker that captures the context var capturedCtx context.Context - mockInvoker := func(ctx context.Context, method string, req, reply interface{}, cc *gp.ClientConn, opts ...gp.CallOption) error { + mockInvoker := func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, opts ...grpc.CallOption) error { capturedCtx = ctx return nil } From 3ca939c7411e047382db9e474f7f8fd08cdc58fd Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:49:48 -0500 Subject: [PATCH 16/27] Use updated version of ci-lint-go action with stdout support --- .github/workflows/golangci_lint.yml | 3 +-- script/lint.sh | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index ac7274cf95..aeb103bde6 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -47,12 +47,11 @@ jobs: - name: golangci-lint ${{ matrix.module }} if: ${{ always() && !contains(join(github.event.pull_request.labels.*.name, ' '), 'allow-lint-issues') }} # NOTE: Keep this version in sync with ACTION_CI_LINT_GO_GIT_TAG in ./script/lint.sh - uses: smartcontractkit/.github/actions/ci-lint-go@ci-lint-go/3.0.0 + uses: smartcontractkit/.github/actions/ci-lint-go@ci-lint-go/v3 with: checkout-repo: false golangci-lint-version: v${{ steps.get-version.outputs.version }} go-directory: ${{ matrix.module }} - golangci-lint-args: --output.text.path=stdout --output.checkstyle.path=${{ matrix.module }}/golangci-lint-report.xml golangci-lint: # Required sink job that waits for all lint jobs to complete diff --git a/script/lint.sh b/script/lint.sh index da256f38ab..84f618c210 100755 --- a/script/lint.sh +++ b/script/lint.sh @@ -27,7 +27,7 @@ if [[ -n "${GOLANGCI_LINT_CONFIG:-}" ]]; then echo "Using user-provided config: $CONFIG_FILE" else # NOTE: Keep this version in sync with the action tag in /.github/workflows/golangci_lint.yml - ACTION_CI_LINT_GO_GIT_TAG="${CI_LINT_GO_VERSION:-ci-lint-go/3.0.0}" + ACTION_CI_LINT_GO_GIT_TAG="${CI_LINT_GO_VERSION:-ci-lint-go/v3}" # Download remote golangci-lint config to gitignored directory REMOTE_CONFIG_URL="https://raw.githubusercontent.com/smartcontractkit/.github/refs/tags/${ACTION_CI_LINT_GO_GIT_TAG}/actions/ci-lint-go/files/golangci-default.yml" CONFIG_FILE="$DIRECTORY/golangci.remote.yml" From a62dc017e7ee423e5722a7cd8825e585e382a192 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 10:56:37 -0500 Subject: [PATCH 17/27] Add debug step to find path to xml report for golangci-lint --- .github/workflows/golangci_lint.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index aeb103bde6..51675aef65 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -53,6 +53,16 @@ jobs: golangci-lint-version: v${{ steps.get-version.outputs.version }} go-directory: ${{ matrix.module }} + - name: Debug + if: ${{ always() }} + run: | + echo "Debugging lint results for module ${{ matrix.module }}" + find . -name "golangci-lint-report.xml" + echo "GITHUB_WORKSPACE: $GITHUB_WORKSPACE" + echo "Current working directory: $(pwd)" + echo "Looking for golangci-lint-report.xml files from workspace root:" + find "$GITHUB_WORKSPACE" -name "golangci-lint-report.xml" + golangci-lint: # Required sink job that waits for all lint jobs to complete if: ${{ github.event_name != 'merge_group' }} From c6979fb5de3a334fab60340049e9b8564849a681 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:11:03 -0500 Subject: [PATCH 18/27] Beef up debugging --- .github/workflows/golangci_lint.yml | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index 51675aef65..98932d0db1 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -57,11 +57,24 @@ jobs: if: ${{ always() }} run: | echo "Debugging lint results for module ${{ matrix.module }}" - find . -name "golangci-lint-report.xml" echo "GITHUB_WORKSPACE: $GITHUB_WORKSPACE" echo "Current working directory: $(pwd)" - echo "Looking for golangci-lint-report.xml files from workspace root:" - find "$GITHUB_WORKSPACE" -name "golangci-lint-report.xml" + echo "" + echo "=== Searching for all XML files from workspace root ===" + find "$GITHUB_WORKSPACE" -name "*.xml" -type f 2>/dev/null || echo "No XML files found" + echo "" + echo "=== Checking expected location ===" + if [ -f "./pkg/chipingress/golangci-lint-report.xml" ]; then + echo "✓ File EXISTS at ./pkg/chipingress/golangci-lint-report.xml" + ls -lh "./pkg/chipingress/golangci-lint-report.xml" + echo "Contents:" + cat "./pkg/chipingress/golangci-lint-report.xml" + else + echo "✗ File DOES NOT EXIST at ./pkg/chipingress/golangci-lint-report.xml" + fi + echo "" + echo "=== Listing all files in chipingress directory ===" + ls -la "./pkg/chipingress/" || echo "Directory doesn't exist" golangci-lint: # Required sink job that waits for all lint jobs to complete From fa439d63a31704f014c06e95479d1e02b5a732a7 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:15:18 -0500 Subject: [PATCH 19/27] Search for all issues to debug --- .github/workflows/golangci_lint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index 98932d0db1..ecefb7e1a0 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -52,6 +52,7 @@ jobs: checkout-repo: false golangci-lint-version: v${{ steps.get-version.outputs.version }} go-directory: ${{ matrix.module }} + only-new-issues: false - name: Debug if: ${{ always() }} From 9e5629263fa50e2bc3edd167e1a002320411387e Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:29:40 -0500 Subject: [PATCH 20/27] Use temporary branch for action whilst debugging --- .github/workflows/golangci_lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index ecefb7e1a0..686b490b81 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -47,7 +47,7 @@ jobs: - name: golangci-lint ${{ matrix.module }} if: ${{ always() && !contains(join(github.event.pull_request.labels.*.name, ' '), 'allow-lint-issues') }} # NOTE: Keep this version in sync with ACTION_CI_LINT_GO_GIT_TAG in ./script/lint.sh - uses: smartcontractkit/.github/actions/ci-lint-go@ci-lint-go/v3 + uses: smartcontractkit/.github/actions/ci-lint-go@dx-2618/golangci-lint # TODO - use versioned release with: checkout-repo: false golangci-lint-version: v${{ steps.get-version.outputs.version }} From e331b538227740694dd2b14c41a13b828bf41ffd Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:47:21 -0500 Subject: [PATCH 21/27] Add more debugging 2 --- .github/workflows/golangci_lint.yml | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index 686b490b81..7bcbbeaace 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -22,6 +22,8 @@ jobs: if: ${{ github.event_name != 'merge_group' }} needs: detect-modules runs-on: ubuntu-latest + env: + GO_DIR: ${{ matrix.module }} # Modules are independent continue-on-error: true strategy: @@ -57,7 +59,9 @@ jobs: - name: Debug if: ${{ always() }} run: | - echo "Debugging lint results for module ${{ matrix.module }}" + module_dir="${{ matrix.module }}" + report_path="${module_dir%/}/golangci-lint-report.xml" + echo "Debugging lint results for module ${module_dir}" echo "GITHUB_WORKSPACE: $GITHUB_WORKSPACE" echo "Current working directory: $(pwd)" echo "" @@ -65,17 +69,17 @@ jobs: find "$GITHUB_WORKSPACE" -name "*.xml" -type f 2>/dev/null || echo "No XML files found" echo "" echo "=== Checking expected location ===" - if [ -f "./pkg/chipingress/golangci-lint-report.xml" ]; then - echo "✓ File EXISTS at ./pkg/chipingress/golangci-lint-report.xml" - ls -lh "./pkg/chipingress/golangci-lint-report.xml" + if [ -f "${report_path}" ]; then + echo "✓ File EXISTS at ${report_path}" + ls -lh "${report_path}" echo "Contents:" - cat "./pkg/chipingress/golangci-lint-report.xml" + cat "${report_path}" else - echo "✗ File DOES NOT EXIST at ./pkg/chipingress/golangci-lint-report.xml" + echo "✗ File DOES NOT EXIST at ${report_path}" fi echo "" - echo "=== Listing all files in chipingress directory ===" - ls -la "./pkg/chipingress/" || echo "Directory doesn't exist" + echo "=== Listing all files in module directory ===" + ls -la "${module_dir%/}/" || echo "Directory doesn't exist" golangci-lint: # Required sink job that waits for all lint jobs to complete From a6031940b23ff0e62f304d5ffe6fd2012f978575 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:52:37 -0500 Subject: [PATCH 22/27] Set golangci-lint args explicitly --- .github/workflows/golangci_lint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index 7bcbbeaace..0cdb5c4fa4 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -54,6 +54,7 @@ jobs: checkout-repo: false golangci-lint-version: v${{ steps.get-version.outputs.version }} go-directory: ${{ matrix.module }} + golangci-lint-args: "--output.text.path=stdout --output.checkstyle.path=${{ matrix.module }}/golangci-lint-report.xml" only-new-issues: false - name: Debug From 29e194830e4be8f3523396c5068342bd1309b0e1 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 12:14:51 -0500 Subject: [PATCH 23/27] Use absolute path --- .github/workflows/golangci_lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index 0cdb5c4fa4..1b6bb96401 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -54,7 +54,7 @@ jobs: checkout-repo: false golangci-lint-version: v${{ steps.get-version.outputs.version }} go-directory: ${{ matrix.module }} - golangci-lint-args: "--output.text.path=stdout --output.checkstyle.path=${{ matrix.module }}/golangci-lint-report.xml" + golangci-lint-args: "--output.text.path=stdout --output.checkstyle.path=${{ github.workspace }}/${{ matrix.module }}/golangci-lint-report.xml" only-new-issues: false - name: Debug From 3b96bdb5b940e055a3e0889339a012e12216b76e Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 12:21:56 -0500 Subject: [PATCH 24/27] Set a uniq artifact name for lint report --- .github/workflows/golangci_lint.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index 1b6bb96401..007e1e933f 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -52,6 +52,7 @@ jobs: uses: smartcontractkit/.github/actions/ci-lint-go@dx-2618/golangci-lint # TODO - use versioned release with: checkout-repo: false + artifact-name: golalngci-lint-report-${{ matrix.module }} golangci-lint-version: v${{ steps.get-version.outputs.version }} go-directory: ${{ matrix.module }} golangci-lint-args: "--output.text.path=stdout --output.checkstyle.path=${{ github.workspace }}/${{ matrix.module }}/golangci-lint-report.xml" From 5a1c7bf86309ba42814ebce6531285b8d6b18210 Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 14:59:22 -0500 Subject: [PATCH 25/27] Sanitize artifact name for linting xml report --- .github/workflows/golangci_lint.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index 007e1e933f..d53618dd1b 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -46,13 +46,21 @@ jobs: version=$(grep '^golangci-lint ' .tool-versions | awk '{print $2}') echo "version=${version}" | tee -a "$GITHUB_OUTPUT" + - name: Sanitize artifact name + id: artifact-name + env: + MODULE: ${{ matrix.module }} + run: | + safe_name=${MODULE//\//-} + echo "value=golangci-lint-report-${safe_name}" | tee -a "$GITHUB_OUTPUT" + - name: golangci-lint ${{ matrix.module }} if: ${{ always() && !contains(join(github.event.pull_request.labels.*.name, ' '), 'allow-lint-issues') }} # NOTE: Keep this version in sync with ACTION_CI_LINT_GO_GIT_TAG in ./script/lint.sh uses: smartcontractkit/.github/actions/ci-lint-go@dx-2618/golangci-lint # TODO - use versioned release with: checkout-repo: false - artifact-name: golalngci-lint-report-${{ matrix.module }} + artifact-name: ${{ steps.artifact-name.outputs.value }} golangci-lint-version: v${{ steps.get-version.outputs.version }} go-directory: ${{ matrix.module }} golangci-lint-args: "--output.text.path=stdout --output.checkstyle.path=${{ github.workspace }}/${{ matrix.module }}/golangci-lint-report.xml" From d74980fea233305b7643aa5419de50ccef09975a Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Wed, 14 Jan 2026 20:52:26 -0500 Subject: [PATCH 26/27] Use latest major tag of action --- .github/workflows/golangci_lint.yml | 2 +- script/lint.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index d53618dd1b..7bf9682686 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -57,7 +57,7 @@ jobs: - name: golangci-lint ${{ matrix.module }} if: ${{ always() && !contains(join(github.event.pull_request.labels.*.name, ' '), 'allow-lint-issues') }} # NOTE: Keep this version in sync with ACTION_CI_LINT_GO_GIT_TAG in ./script/lint.sh - uses: smartcontractkit/.github/actions/ci-lint-go@dx-2618/golangci-lint # TODO - use versioned release + uses: smartcontractkit/.github/actions/ci-lint-go@ci-lint-go/v4 with: checkout-repo: false artifact-name: ${{ steps.artifact-name.outputs.value }} diff --git a/script/lint.sh b/script/lint.sh index 84f618c210..75fd0786dd 100755 --- a/script/lint.sh +++ b/script/lint.sh @@ -27,7 +27,7 @@ if [[ -n "${GOLANGCI_LINT_CONFIG:-}" ]]; then echo "Using user-provided config: $CONFIG_FILE" else # NOTE: Keep this version in sync with the action tag in /.github/workflows/golangci_lint.yml - ACTION_CI_LINT_GO_GIT_TAG="${CI_LINT_GO_VERSION:-ci-lint-go/v3}" + ACTION_CI_LINT_GO_GIT_TAG="${CI_LINT_GO_VERSION:-ci-lint-go/v4}" # Download remote golangci-lint config to gitignored directory REMOTE_CONFIG_URL="https://raw.githubusercontent.com/smartcontractkit/.github/refs/tags/${ACTION_CI_LINT_GO_GIT_TAG}/actions/ci-lint-go/files/golangci-default.yml" CONFIG_FILE="$DIRECTORY/golangci.remote.yml" From b303b53f24bf20974eed1171b4831a9da795e01f Mon Sep 17 00:00:00 2001 From: chainchad <96362174+chainchad@users.noreply.github.com> Date: Thu, 15 Jan 2026 10:41:33 -0500 Subject: [PATCH 27/27] Fix artifact name --- .github/workflows/golangci_lint.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/golangci_lint.yml b/.github/workflows/golangci_lint.yml index 23944d1be0..5392366e45 100644 --- a/.github/workflows/golangci_lint.yml +++ b/.github/workflows/golangci_lint.yml @@ -49,7 +49,12 @@ jobs: env: MODULE: ${{ matrix.module }} run: | - safe_name=${MODULE//\//-} + safe_name="${MODULE#./}" + safe_name="${safe_name#/}" + safe_name="${safe_name//\//-}" + if [[ -z "$safe_name" || "$safe_name" = "." ]]; then + safe_name="root" + fi echo "value=golangci-lint-report-${safe_name}" | tee -a "$GITHUB_OUTPUT" - name: golangci-lint ${{ matrix.module }}