diff --git a/events/codepipeline_cloudwatch.go b/events/codepipeline_cloudwatch.go new file mode 100644 index 00000000..e51fea12 --- /dev/null +++ b/events/codepipeline_cloudwatch.go @@ -0,0 +1,107 @@ +package events + +import ( + "time" +) + +const ( + CodePipelineEventSource = "aws.codepipeline" + CodePipelineExecutionEventDetailType = "CodePipeline Pipeline Execution State Change" + CodePipelineActionEventDetailType = "CodePipeline Action Execution State Change" + CodePipelineStageEventDetailType = "CodePipeline Stage Execution State Change" +) + +type CodePipelineStageState string + +const ( + CodePipelineStageStateStarted CodePipelineStageState = "STARTED" + CodePipelineStageStateSucceeded CodePipelineStageState = "SUCCEEDED" + CodePipelineStageStateResumed CodePipelineStageState = "RESUMED" + CodePipelineStageStateFailed CodePipelineStageState = "FAILED" + CodePipelineStageStateCanceled CodePipelineStageState = "CANCELED" +) + +type CodePipelineState string + +const ( + CodePipelineStateStarted CodePipelineState = "STARTED" + CodePipelineStateSucceeded CodePipelineState = "SUCCEEDED" + CodePipelineStateResumed CodePipelineState = "RESUMED" + CodePipelineStateFailed CodePipelineState = "FAILED" + CodePipelineStateCanceled CodePipelineState = "CANCELED" + CodePipelineStateSuperseded CodePipelineState = "SUPERSEDED" +) + +type CodePipelineActionState string + +const ( + CodePipelineActionStateStarted CodePipelineActionState = "STARTED" + CodePipelineActionStateSucceeded CodePipelineActionState = "SUCCEEDED" + CodePipelineActionStateFailed CodePipelineActionState = "FAILED" + CodePipelineActionStateCanceled CodePipelineActionState = "CANCELED" +) + +// CodePipelineEvent is documented at: +// https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/EventTypes.html#codepipeline_event_type +type CodePipelineCloudWatchEvent struct { + // Version is the version of the event's schema. + Version string `json:"version"` + + // ID is the GUID of this event. + ID string `json:"id"` + + // DetailType informs the schema of the Detail field. For deployment state-change + // events, the value should be equal to CodePipelineDeploymentEventDetailType. + // For instance state-change events, the value should be equal to + // CodePipelineInstanceEventDetailType. + DetailType string `json:"detail-type"` + + // Source should be equal to CodePipelineEventSource. + Source string `json:"source"` + + // AccountID is the id of the AWS account from which the event originated. + AccountID string `json:"account"` + + // Time is the event's timestamp. + Time time.Time `json:"time"` + + // Region is the AWS region from which the event originated. + Region string `json:"region"` + + // Resources is a list of ARNs of CodePipeline applications and deployment + // groups that this event pertains to. + Resources []string `json:"resources"` + + // Detail contains information specific to a deployment event. + Detail CodePipelineEventDetail `json:"detail"` +} + +type CodePipelineEventDetail struct { + Pipeline string `json:"pipeline"` + + // From live testing this is always int64 not string as documented + Version int64 `json:"version"` + + ExecutionID string `json:"execution-id"` + + Stage string `json:"stage"` + + Action string `json:"action"` + + State CodePipelineState `json:"state"` + + Region string `json:"region"` + + Type CodePipelineEventDetailType `json:"type"` +} + +type CodePipelineEventDetailType struct { + Owner string `json:"owner"` + + Category string `json:"category"` + + Provider string `json:"provider"` + + // From published EventBridge schema registry this is always int64 not string as documented + Version int64 `json:"version"` +} diff --git a/events/codepipeline_cloudwatch_test.go b/events/codepipeline_cloudwatch_test.go new file mode 100644 index 00000000..e927e705 --- /dev/null +++ b/events/codepipeline_cloudwatch_test.go @@ -0,0 +1,99 @@ +package events + +import ( + "encoding/json" + "github.com/stretchr/testify/require" + "io/ioutil" + "testing" + "time" +) + +func TestUnmarshalCodePipelineEvent(t *testing.T) { + tests := []struct { + input string + expect CodePipelineCloudWatchEvent + }{ + { + input: "testdata/codepipeline-action-execution-stage-change-event.json", + expect: CodePipelineCloudWatchEvent{ + Version: "0", + ID: "CWE-event-id", + DetailType: "CodePipeline Action Execution State Change", + Source: "aws.codepipeline", + AccountID: "123456789012", + Time: time.Date(2017, 04, 22, 3, 31, 47, 0, time.UTC), + Region: "us-east-1", + Resources: []string{ + "arn:aws:codepipeline:us-east-1:123456789012:pipeline:myPipeline", + }, + Detail: CodePipelineEventDetail{ + Pipeline: "myPipeline", + Version: 1, + ExecutionID: "01234567-0123-0123-0123-012345678901", + Stage: "Prod", + Action: "myAction", + State: "STARTED", + Region: "us-west-2", + Type: CodePipelineEventDetailType{ + Owner: "AWS", + Category: "Deploy", + Provider: "CodeDeploy", + Version: 1, + }, + }, + }, + }, + { + input: "testdata/codepipeline-execution-stage-change-event.json", + expect: CodePipelineCloudWatchEvent{ + Version: "0", + ID: "CWE-event-id", + DetailType: "CodePipeline Stage Execution State Change", + Source: "aws.codepipeline", + AccountID: "123456789012", + Time: time.Date(2017, 04, 22, 3, 31, 47, 0, time.UTC), + Region: "us-east-1", + Resources: []string{ + "arn:aws:codepipeline:us-east-1:123456789012:pipeline:myPipeline", + }, + Detail: CodePipelineEventDetail{ + Pipeline: "myPipeline", + Version: 1, + ExecutionID: "01234567-0123-0123-0123-012345678901", + State: "STARTED", + }, + }, + }, + { + input: "testdata/codepipeline-execution-state-change-event.json", + expect: CodePipelineCloudWatchEvent{ + Version: "0", + ID: "CWE-event-id", + DetailType: "CodePipeline Pipeline Execution State Change", + Source: "aws.codepipeline", + AccountID: "123456789012", + Time: time.Date(2017, 04, 22, 3, 31, 47, 0, time.UTC), + Region: "us-east-1", + Resources: []string{ + "arn:aws:codepipeline:us-east-1:123456789012:pipeline:myPipeline", + }, + Detail: CodePipelineEventDetail{ + Pipeline: "myPipeline", + Version: 1, + ExecutionID: "01234567-0123-0123-0123-012345678901", + State: "STARTED", + }, + }, + }, + } + + for _, testcase := range tests { + data, err := ioutil.ReadFile(testcase.input) + require.NoError(t, err) + + var actual CodePipelineCloudWatchEvent + require.NoError(t, json.Unmarshal(data, &actual)) + + require.Equal(t, testcase.expect, actual) + } +} diff --git a/events/testdata/codepipeline-action-execution-stage-change-event.json b/events/testdata/codepipeline-action-execution-stage-change-event.json new file mode 100644 index 00000000..826fa77a --- /dev/null +++ b/events/testdata/codepipeline-action-execution-stage-change-event.json @@ -0,0 +1,27 @@ +{ + "version": "0", + "id": "CWE-event-id", + "detail-type": "CodePipeline Action Execution State Change", + "source": "aws.codepipeline", + "account": "123456789012", + "time": "2017-04-22T03:31:47Z", + "region": "us-east-1", + "resources": [ + "arn:aws:codepipeline:us-east-1:123456789012:pipeline:myPipeline" + ], + "detail": { + "pipeline": "myPipeline", + "version": 1, + "execution-id": "01234567-0123-0123-0123-012345678901", + "stage": "Prod", + "action": "myAction", + "state": "STARTED", + "region":"us-west-2", + "type": { + "owner": "AWS", + "category": "Deploy", + "provider": "CodeDeploy", + "version": 1 + } + } +} \ No newline at end of file diff --git a/events/testdata/codepipeline-execution-stage-change-event.json b/events/testdata/codepipeline-execution-stage-change-event.json new file mode 100644 index 00000000..6a76b4c3 --- /dev/null +++ b/events/testdata/codepipeline-execution-stage-change-event.json @@ -0,0 +1,18 @@ +{ + "version": "0", + "id": "CWE-event-id", + "detail-type": "CodePipeline Stage Execution State Change", + "source": "aws.codepipeline", + "account": "123456789012", + "time": "2017-04-22T03:31:47Z", + "region": "us-east-1", + "resources": [ + "arn:aws:codepipeline:us-east-1:123456789012:pipeline:myPipeline" + ], + "detail": { + "pipeline": "myPipeline", + "version": 1, + "state": "STARTED", + "execution-id": "01234567-0123-0123-0123-012345678901" + } +} \ No newline at end of file diff --git a/events/testdata/codepipeline-execution-state-change-event.json b/events/testdata/codepipeline-execution-state-change-event.json new file mode 100644 index 00000000..32c2bcb4 --- /dev/null +++ b/events/testdata/codepipeline-execution-state-change-event.json @@ -0,0 +1,18 @@ +{ + "version": "0", + "id": "CWE-event-id", + "detail-type": "CodePipeline Pipeline Execution State Change", + "source": "aws.codepipeline", + "account": "123456789012", + "time": "2017-04-22T03:31:47Z", + "region": "us-east-1", + "resources": [ + "arn:aws:codepipeline:us-east-1:123456789012:pipeline:myPipeline" + ], + "detail": { + "pipeline": "myPipeline", + "version": 1, + "state": "STARTED", + "execution-id": "01234567-0123-0123-0123-012345678901" + } +} \ No newline at end of file