Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
137 changes: 137 additions & 0 deletions EiffelArtifactDeployedEventV0_1_0.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// Copyright Axis Communications AB.
//
// For a full list of individual contributors, please see the commit history.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// THIS FILE IS AUTOMATICALLY GENERATED AND MUST NOT BE EDITED BY HAND.

package eiffelevents

import (
"fmt"
"reflect"
"time"

"github.com/clarketm/json"
"github.com/google/uuid"
)

// NewArtifactDeployedV0_1_0 creates a new struct pointer that represents
// major version 0 of EiffelArtifactDeployedEvent.
// The returned struct has all required meta members populated.
// The event version is set to the most recent 0.x.x
// currently known by this SDK.
func NewArtifactDeployedV0_1_0(modifiers ...Modifier) (*ArtifactDeployedV0_1_0, error) {
var event ArtifactDeployedV0_1_0
event.Meta.Type = "EiffelArtifactDeployedEvent"
event.Meta.ID = uuid.NewString()
event.Meta.Version = eventTypeTable[event.Meta.Type][0].latestVersion
event.Meta.Time = time.Now().UnixMilli()
for _, modifier := range modifiers {
if err := modifier(&event); err != nil {
return nil, fmt.Errorf("error applying modifier to new ArtifactDeployedV0_1_0: %w", err)
}
}
return &event, nil
}

// MarshalJSON returns the JSON encoding of the event.
func (e *ArtifactDeployedV0_1_0) MarshalJSON() ([]byte, error) {
// The standard encoding/json package doesn't honor omitempty for
// non-pointer structs (it doesn't recurse into values, only examines
// the immediate value). This is a not terribly elegant way of making
// sure that this struct is marshaled by github.com/clarketm/json
// without the infinite loop we'd get by just passing the struct to
// github.com/clarketm/json.Marshal.
//
// Make sure the links slice is non-null so that non-initialized slices
// get serialized as "[]" instead of "null".
links := e.Links
if links == nil {
links = make(EventLinksV1, 0)
}
s := struct {
Data *ArtDV0_1_0Data `json:"data"`
Links EventLinksV1 `json:"links"`
Meta *MetaV3 `json:"meta"`
}{
Data: &e.Data,
Links: links,
Meta: &e.Meta,
}
return json.Marshal(s)
}

func (e *ArtifactDeployedV0_1_0) SetField(fieldName string, value interface{}) error {
return setField(reflect.ValueOf(e), fieldName, value)
}

// String returns the JSON encoding of the event.
func (e *ArtifactDeployedV0_1_0) String() string {
b, err := e.MarshalJSON()
if err != nil {
// This should never happen, and if it does happen it's not clear that
// there's a reasonable way to recover. Returning an error message
// instead of the JSON string won't end well.
panic(err)
}
return string(b)
}

var _ FieldSetter = &ArtifactDeployedV0_1_0{}
var _ MetaTeller = &ArtifactDeployedV0_1_0{}

// ID returns the value of the meta.id field.
func (e ArtifactDeployedV0_1_0) ID() string {
return e.Meta.ID
}

// Type returns the value of the meta.type field.
func (e ArtifactDeployedV0_1_0) Type() string {
return e.Meta.Type
}

// Version returns the value of the meta.version field.
func (e ArtifactDeployedV0_1_0) Version() string {
return e.Meta.Version
}

// Time returns the value of the meta.time field.
func (e ArtifactDeployedV0_1_0) Time() int64 {
return e.Meta.Time
}

// DomainID returns the value of the meta.source.domainId field.
func (e ArtifactDeployedV0_1_0) DomainID() string {
return e.Meta.Source.DomainID
}

type ArtifactDeployedV0_1_0 struct {
// Mandatory fields
Data ArtDV0_1_0Data `json:"data"`
Links EventLinksV1 `json:"links"`
Meta MetaV3 `json:"meta"`

// Optional fields

}

type ArtDV0_1_0Data struct {
// Mandatory fields

// Optional fields
CustomData []CustomDataV1 `json:"customData,omitempty"`
Description string `json:"description,omitempty"`
URI string `json:"uri,omitempty"`
}
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,11 @@ below.
## Creating new events

The struct types used to represent Eiffel events are named after the event
types without the "Eiffel" prefix and "Event" suffix, and the event's major
version as a suffix. Hence, each event's major version gets its own struct.
types without the "Eiffel" prefix and "Event" suffix, and with a version suffix.
For non-experimental event versions (1.0.0 and up) the version suffix is the
event's major version (i.e. each major version gets its own struct) while for
experimental event versions (0.x.y) every single version gets its own struct
(because every version is allowed to contain backwards incompatible changes).

The following example shows two methods of creating events, with and without
a factory.
Expand Down
1 change: 1 addition & 0 deletions events_test_roundtripdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ var eventRoundTripTestTable = []struct {
{"protocol/examples/events/EiffelArtifactCreatedEvent/dependent.json", &ArtifactCreatedV3{}},
{"protocol/examples/events/EiffelArtifactCreatedEvent/interface.json", &ArtifactCreatedV3{}},
{"protocol/examples/events/EiffelArtifactCreatedEvent/simple.json", &ArtifactCreatedV3{}},
{"protocol/examples/events/EiffelArtifactDeployedEvent/simple.json", &ArtifactDeployedV0_1_0{}},
{"protocol/examples/events/EiffelArtifactPublishedEvent/multifile.json", &ArtifactPublishedV3{}},
{"protocol/examples/events/EiffelArtifactPublishedEvent/simple.json", &ArtifactPublishedV3{}},
{"protocol/examples/events/EiffelArtifactReusedEvent/simple.json", &ArtifactReusedV3{}},
Expand Down
9 changes: 6 additions & 3 deletions eventtypetable.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ var eventTypeTable = map[string]map[int64]majorEventVersion{
2: majorEventVersion{reflect.TypeOf(ArtifactCreatedV2{}), "2.0.0"},
3: majorEventVersion{reflect.TypeOf(ArtifactCreatedV3{}), "3.3.0"},
},
"EiffelArtifactDeployedEvent": {
0: majorEventVersion{reflect.TypeOf(ArtifactDeployedV0_1_0{}), "0.1.0"},
},
"EiffelArtifactPublishedEvent": {
1: majorEventVersion{reflect.TypeOf(ArtifactPublishedV1{}), "1.1.0"},
2: majorEventVersion{reflect.TypeOf(ArtifactPublishedV2{}), "2.0.0"},
Expand All @@ -79,7 +82,7 @@ var eventTypeTable = map[string]map[int64]majorEventVersion{
"EiffelConfidenceLevelModifiedEvent": {
1: majorEventVersion{reflect.TypeOf(ConfidenceLevelModifiedV1{}), "1.1.0"},
2: majorEventVersion{reflect.TypeOf(ConfidenceLevelModifiedV2{}), "2.0.0"},
3: majorEventVersion{reflect.TypeOf(ConfidenceLevelModifiedV3{}), "3.2.0"},
3: majorEventVersion{reflect.TypeOf(ConfidenceLevelModifiedV3{}), "3.3.0"},
},
"EiffelEnvironmentDefinedEvent": {
1: majorEventVersion{reflect.TypeOf(EnvironmentDefinedV1{}), "1.1.0"},
Expand All @@ -100,7 +103,7 @@ var eventTypeTable = map[string]map[int64]majorEventVersion{
1: majorEventVersion{reflect.TypeOf(IssueVerifiedV1{}), "1.1.0"},
2: majorEventVersion{reflect.TypeOf(IssueVerifiedV2{}), "2.0.0"},
3: majorEventVersion{reflect.TypeOf(IssueVerifiedV3{}), "3.0.0"},
4: majorEventVersion{reflect.TypeOf(IssueVerifiedV4{}), "4.2.0"},
4: majorEventVersion{reflect.TypeOf(IssueVerifiedV4{}), "4.3.0"},
},
"EiffelSourceChangeCreatedEvent": {
1: majorEventVersion{reflect.TypeOf(SourceChangeCreatedV1{}), "1.1.0"},
Expand Down Expand Up @@ -131,7 +134,7 @@ var eventTypeTable = map[string]map[int64]majorEventVersion{
"EiffelTestCaseTriggeredEvent": {
1: majorEventVersion{reflect.TypeOf(TestCaseTriggeredV1{}), "1.1.0"},
2: majorEventVersion{reflect.TypeOf(TestCaseTriggeredV2{}), "2.0.0"},
3: majorEventVersion{reflect.TypeOf(TestCaseTriggeredV3{}), "3.2.0"},
3: majorEventVersion{reflect.TypeOf(TestCaseTriggeredV3{}), "3.4.0"},
},
"EiffelTestExecutionRecipeCollectionCreatedEvent": {
1: majorEventVersion{reflect.TypeOf(TestExecutionRecipeCollectionCreatedV1{}), "1.0.0"},
Expand Down
35 changes: 25 additions & 10 deletions internal/cmd/eventgen/eventtypes.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import (
"fmt"
"os"
"path/filepath"
"strconv"
"strings"

jsschema "github.com/lestrrat-go/jsschema"
"gopkg.in/yaml.v3"
Expand Down Expand Up @@ -63,7 +65,7 @@ func (t *goInterface) String() string {
// those structs) for the latest version within each major version of each type.
func generateTypes(schemaDefs map[string][]schemaDefinitionRenderer, outputDir string) error {
for _, defs := range schemaDefs {
for majorVersion, schema := range latestMajorVersions(defs) {
for significantVersion, schema := range significantVersions(defs) {
schemaFile, err := os.Open(schema.Filename())
if err != nil {
return err
Expand All @@ -80,7 +82,7 @@ func generateTypes(schemaDefs map[string][]schemaDefinitionRenderer, outputDir s
return err
}

outputFile := filepath.Join(outputDir, fmt.Sprintf("%sV%d.go", schema.TypeName(), majorVersion))
outputFile := filepath.Join(outputDir, fmt.Sprintf("%sV%s.go", schema.TypeName(), strings.ReplaceAll(significantVersion, ".", "_")))
if err = schema.Render(&jsonDef, outputFile); err != nil {
return err
}
Expand All @@ -89,17 +91,30 @@ func generateTypes(schemaDefs map[string][]schemaDefinitionRenderer, outputDir s
return nil
}

// latestMajorVersions inspects a list of schema definitions for a single type and
// maps each encountered major version to the schemaDefinitionRenderer that
// represents the most recent minor.patch version within that major version.
func latestMajorVersions(schemas []schemaDefinitionRenderer) map[int64]schemaDefinitionRenderer {
majorVersions := map[int64]schemaDefinitionRenderer{}
// significantVersions inspects a list of schema definitions for a single type and maps the type
// versions to generate to the corresponding schemaDefinitionRenderers. For non-experimental
// event versions, the type version will be the major version of the most recent major.minor.patch
// version within each major version will be returned, while all experimental event versions will
// be returned with the type version set to the full major.minor.patch version.
//
// For example, given the versions (0.1.0, 0.2.0, 1.0.0, 1.1.0, 2.0.0) a map with the keys
// (0.1.0, 0.2.0, 1, 2) will be returned.
func significantVersions(schemas []schemaDefinitionRenderer) map[string]schemaDefinitionRenderer {
versions := map[string]schemaDefinitionRenderer{}
for _, schema := range schemas {
if current, exists := majorVersions[schema.Version().Major()]; !exists || current.Version().LessThan(schema.Version()) {
majorVersions[schema.Version().Major()] = schema
// Keep all schemas for experimental versions.
if schema.Version().Major() == 0 {
versions[schema.Version().String()] = schema
continue
}

// Only keep the latest non-experimental version.
majorStr := strconv.Itoa(int(schema.Version().Major()))
if current, exists := versions[majorStr]; !exists || current.Version().LessThan(schema.Version()) {
versions[majorStr] = schema
}
}
return majorVersions
return versions
}

// goTypeFromSchema returns a goType that represents a node in a JSON schema.
Expand Down
35 changes: 27 additions & 8 deletions internal/cmd/eventgen/eventtypes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ func TestLatestMajorVersions(t *testing.T) {
testcases := []struct {
name string
input []schemaDefinitionRenderer
expected map[int64]schemaDefinitionRenderer
expected map[string]schemaDefinitionRenderer
}{
{
name: "Empty input map",
input: []schemaDefinitionRenderer{},
expected: map[int64]schemaDefinitionRenderer{},
expected: map[string]schemaDefinitionRenderer{},
},
{
name: "Multiple major versions",
Expand All @@ -59,25 +59,44 @@ func TestLatestMajorVersions(t *testing.T) {
definitionFile: definitionFile{"/path/to/EiffelActivityStartedEvent/4.2.0.json", "EiffelActivityStartedEvent", semver.MustParse("4.2.0")},
},
},
expected: map[int64]schemaDefinitionRenderer{
1: &eventDefinitionFile{
expected: map[string]schemaDefinitionRenderer{
"1": &eventDefinitionFile{
definitionFile: definitionFile{"/path/to/EiffelActivityStartedEvent/1.1.0.json", "EiffelActivityStartedEvent", semver.MustParse("1.1.0")},
},
2: &eventDefinitionFile{
"2": &eventDefinitionFile{
definitionFile: definitionFile{"/path/to/EiffelActivityStartedEvent/2.0.0.json", "EiffelActivityStartedEvent", semver.MustParse("2.0.0")},
},
3: &eventDefinitionFile{
"3": &eventDefinitionFile{
definitionFile: definitionFile{"/path/to/EiffelActivityStartedEvent/3.0.0.json", "EiffelActivityStartedEvent", semver.MustParse("3.0.0")},
},
4: &eventDefinitionFile{
"4": &eventDefinitionFile{
definitionFile: definitionFile{"/path/to/EiffelActivityStartedEvent/4.2.0.json", "EiffelActivityStartedEvent", semver.MustParse("4.2.0")},
},
},
},
{
name: "Experimental versions",
input: []schemaDefinitionRenderer{
&eventDefinitionFile{
definitionFile: definitionFile{"/path/to/EiffelArtifactDeployedEvent/0.1.0.json", "EiffelArtifactDeployedEvent", semver.MustParse("0.1.0")},
},
&eventDefinitionFile{
definitionFile: definitionFile{"/path/to/EiffelArtifactDeployedEvent/0.2.0.json", "EiffelArtifactDeployedEvent", semver.MustParse("0.2.0")},
},
},
expected: map[string]schemaDefinitionRenderer{
"0.1.0": &eventDefinitionFile{
definitionFile: definitionFile{"/path/to/EiffelArtifactDeployedEvent/0.1.0.json", "EiffelArtifactDeployedEvent", semver.MustParse("0.1.0")},
},
"0.2.0": &eventDefinitionFile{
definitionFile: definitionFile{"/path/to/EiffelArtifactDeployedEvent/0.2.0.json", "EiffelArtifactDeployedEvent", semver.MustParse("0.2.0")},
},
},
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
actual := latestMajorVersions(tc.input)
actual := significantVersions(tc.input)
assert.Equal(t, tc.expected, actual)
})
}
Expand Down
20 changes: 15 additions & 5 deletions internal/cmd/eventgen/eventtypetable.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ import (
"strings"
"text/template"

"github.com/Masterminds/semver"
"github.com/eiffel-community/eiffelevents-sdk-go"
"github.com/eiffel-community/eiffelevents-sdk-go/internal/codetemplate"
)

type MajorEventVersion struct {
StructName string
LatestVersion string
latest *semver.Version
}

//go:embed templates/eventtypetable.tmpl
Expand All @@ -39,17 +41,25 @@ var eventTableFileTemplate string
func generateEventTypeTable(schemas map[string][]schemaDefinitionRenderer, outputFile string) error {
table := make(map[string]map[int]MajorEventVersion)
for _, eventSchemas := range schemas {
latestVersions := latestMajorVersions(eventSchemas)
for majorVersion, schema := range latestVersions {
latestVersions := significantVersions(eventSchemas)
for _, schema := range latestVersions {
if !strings.HasSuffix(schema.TypeName(), "Event") {
continue
}
if table[schema.TypeName()] == nil {
table[schema.TypeName()] = make(map[int]MajorEventVersion)
}
table[schema.TypeName()][int(majorVersion)] = MajorEventVersion{
eiffelevents.VersionedStructName(schema.TypeName(), schema.Version()),
schema.Version().String(),

// For non-experimental event versions this conditional is unnecessary since significantVersions()
// has already weeded out non-latest versions, but for experimental versions we need to make sure
// we fill the table with the latest one (and the latest one only).
major := int(schema.Version().Major())
if current, exists := table[schema.TypeName()][major]; !exists || current.latest.LessThan(schema.Version()) {
table[schema.TypeName()][major] = MajorEventVersion{
eiffelevents.VersionedStructName(schema.TypeName(), schema.Version()),
schema.Version().String(),
schema.Version(),
}
}
}
}
Expand Down
Loading