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
8 changes: 5 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,12 +49,14 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v7
with:
go-version: 'stable'
# Lint at the module's own Go. golangci-lint is a prebuilt binary
# that can only load stdlib export data from the Go it was built
# with; following 'stable' turns every Go release into a red lint
# job on every PR, triggered by nothing in the repo.
go-version-file: go.mod

# golangci-lint v2 subsumes gofmt, gci, staticcheck, govet and the rest;
# config in .golangci.yml. Generated files are auto-excluded by header.
# The official action ships a golangci-lint binary whose type-checker
# matches the Go toolchain, avoiding stdlib version skew.
- name: golangci-lint
uses: golangci/golangci-lint-action@v9
with:
Expand Down
37 changes: 37 additions & 0 deletions flashduty_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"io"
"net/http"
"net/http/httptest"
"reflect"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -274,6 +275,42 @@ func TestIncidentNotificationOverrideOmitsUnsetPreference(t *testing.T) {
}
}

func TestCustomFieldValuesReachTheWire(t *testing.T) {
c, _ := NewClient("KEY", WithBaseURL("https://api.flashcat.cloud"), WithLogger(noopLogger{}))
values := CustomFieldValues{"region": "cn-beijing", "impact_users": float64(42), "tags": []any{"db"}}

tests := []struct {
name string
path string
body any
field string
}{
{"create incident", "/incident/create", &CreateIncidentRequest{IncidentSeverity: "Critical", Fields: values}, "fields"},
{"ack incident", "/incident/ack", &AckIncidentRequest{CustomFields: values}, "custom_fields"},
{"resolve incident", "/incident/resolve", &ResolveIncidentRequest{CustomFields: values}, "custom_fields"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
req, err := c.newRequest(context.Background(), http.MethodPost, tt.path, tt.body)
if err != nil {
t.Fatal(err)
}
body, err := io.ReadAll(req.Body)
if err != nil {
t.Fatal(err)
}
var payload map[string]any
if err := json.Unmarshal(body, &payload); err != nil {
t.Fatal(err)
}
got, _ := payload[tt.field].(map[string]any)
if !reflect.DeepEqual(got, map[string]any(values)) {
t.Fatalf("%s = %#v, want %#v (body = %s)", tt.field, payload[tt.field], values, body)
}
})
}
}

func TestNewRequestAppliesHookAndHeaders(t *testing.T) {
c, _ := NewClient("KEY",
WithRequestHeaders(map[string][]string{"X-Static": {"s"}}),
Expand Down
4 changes: 4 additions & 0 deletions internal/cmd/gen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,10 @@ func (g *Gen) emitModels() string {
// a map payload (e.g. name -> count), not a struct.
v := g.goTypeOf(asMap(s["additionalProperties"]), goName(name)+"Value")
fmt.Fprintf(&enumsAndAliases, "// %s is a map response payload.\ntype %s map[string]%s\n\n", goName(name), goName(name), v)
case typeStr(s) == "object" && len(asMap(s["properties"])) == 0 && s["additionalProperties"] == true:
// A bare object with additionalProperties: true carries arbitrary
// keys (e.g. custom field values); a struct would drop them all.
fmt.Fprintf(&enumsAndAliases, "// %s is a free-form JSON object.\ntype %s map[string]any\n\n", goName(name), goName(name))
case typeStr(s) == "string", typeStr(s) == "integer", typeStr(s) == "number", typeStr(s) == "boolean":
gt := g.goTypeOf(s, goName(name))
fmt.Fprintf(&enumsAndAliases, "type %s %s\n\n", goName(name), gt)
Expand Down
6 changes: 3 additions & 3 deletions models_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading