Skip to content

Commit 3987ad3

Browse files
authored
chore(test) - Update to use github actions (#210)
* Switch to using github actions for PR testing
1 parent fb764a7 commit 3987ad3

25 files changed

+500
-75
lines changed

.github/workflows/pr-ci.yml

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# This workflow will install Python dependencies, run tests and lint with a single version of Python
2+
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
3+
4+
name: CloudFormation GO Plugin CI
5+
6+
on:
7+
push:
8+
branches: [ master ]
9+
pull_request:
10+
branches: [ master ]
11+
12+
jobs:
13+
build:
14+
env:
15+
AWS_DEFAULT_REGION: us-east-1
16+
runs-on: ubuntu-latest
17+
strategy:
18+
matrix:
19+
python: [3.6, 3.7, 3.8]
20+
steps:
21+
- uses: actions/checkout@v2
22+
- uses: actions/setup-go@v3
23+
with:
24+
go-version: '>=1.17.0'
25+
- name: Set up Python ${{ matrix.python }}
26+
uses: actions/setup-python@v2
27+
with:
28+
python-version: ${{ matrix.python }}
29+
- name: Install dependencies
30+
run: |
31+
pip install pre-commit
32+
pip install --upgrade mypy 'attrs==19.2.0' -r https://raw.githubusercontent.com/aws-cloudformation/aws-cloudformation-rpdk/master/requirements.txt
33+
go install github.com/go-critic/go-critic/cmd/gocritic@latest
34+
go install golang.org/x/tools/cmd/goimports@latest
35+
go install github.com/fzipp/gocyclo/cmd/gocyclo@latest
36+
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.50.1
37+
- name: Install plugin
38+
run: |
39+
pip install .
40+
- name: pre-commit checks
41+
run: |
42+
pre-commit run --all-files

.pre-commit-config.yaml

+63-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v2.0.0
3+
rev: v4.3.0
44
hooks:
55
- id: check-case-conflict
66
- id: end-of-file-fixer
@@ -17,14 +17,73 @@ repos:
1717
- id: check-merge-conflict
1818
- id: check-yaml
1919
- repo: https://github.com/pre-commit/mirrors-isort
20-
rev: v4.3.21
20+
rev: v5.10.1
2121
hooks:
2222
- id: isort
2323
- repo: https://github.com/ambv/black
24-
rev: stable
24+
rev: 22.10.0
2525
hooks:
2626
- id: black
27+
- repo: https://github.com/pycqa/flake8
28+
rev: '5.0.4'
29+
hooks:
30+
- id: flake8
31+
additional_dependencies:
32+
- flake8-bugbear>=19.3.0
33+
- flake8-builtins>=1.4.1
34+
- flake8-commas>=2.0.0
35+
- flake8-comprehensions>=2.1.0
36+
- flake8-debugger>=3.1.0
37+
- flake8-pep3101>=1.2.1
38+
# language_version: python3.6
39+
exclude: templates/
40+
- repo: https://github.com/pre-commit/pygrep-hooks
41+
rev: v1.9.0
42+
hooks:
43+
- id: python-check-blanket-noqa
44+
- id: python-check-mock-methods
45+
- id: python-no-log-warn
46+
- repo: https://github.com/PyCQA/bandit
47+
rev: "1.7.4"
48+
hooks:
49+
- id: bandit
50+
files: ^python/
51+
additional_dependencies:
52+
- "importlib-metadata<5" # https://github.com/PyCQA/bandit/issues/956
53+
- repo: local
54+
hooks:
55+
- id: pylint-local
56+
name: pylint-local
57+
description: Run pylint in the local virtualenv
58+
entry: pylint "setup.py" "python/" "tests/"
59+
language: system
60+
# ignore all files, run on hard-coded modules instead
61+
pass_filenames: false
62+
always_run: true
63+
- id: pytest-local
64+
name: pytest-local
65+
description: Run pytest in the local virtualenv
66+
entry: >
67+
pytest
68+
--cov-report=term
69+
--cov-report=html
70+
--cov="rpdk.go"
71+
--durations=5
72+
"tests/"
73+
language: system
74+
# ignore all files, run on hard-coded modules instead
75+
pass_filenames: false
76+
always_run: true
2777
- repo: https://github.com/dnephin/pre-commit-golang
28-
rev: master
78+
rev: v0.5.1
2979
hooks:
3080
- id: go-fmt
81+
# - id: go-vet
82+
- id: go-imports
83+
- id: go-cyclo
84+
args: [-over=20]
85+
- id: golangci-lint
86+
- id: go-critic
87+
- id: go-unit-tests
88+
- id: go-build
89+
- id: go-mod-tidy

.pylintrc

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[MASTER]
2+
3+
ignore=CVS,models.py,handlers.py,hook_models.py,hook_handlers.py,target_model.py
4+
jobs=1
5+
persistent=yes
6+
7+
[MESSAGES CONTROL]
8+
9+
disable=
10+
missing-docstring, # not everything needs a docstring
11+
fixme, # work in progress
12+
bad-continuation, # clashes with black
13+
too-few-public-methods, # triggers when inheriting
14+
ungrouped-imports, # clashes with isort
15+
duplicate-code, # broken, setup.py
16+
wrong-import-order, # isort has precedence
17+
18+
[BASIC]
19+
20+
good-names=e,ex,f,fp,i,j,k,v,n,_
21+
22+
[FORMAT]
23+
24+
indent-string=' '
25+
max-line-length=88

buildspec.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ phases:
88
- pip install pre-commit
99
build:
1010
commands:
11-
- pre-commit run --all-files
11+
- pre-commit --version

cfn/cfn.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ func makeEventFunc(h Handler) eventFunc {
107107
log.Printf("Error: %v", err)
108108
m.PublishExceptionMetric(time.Now(), event.Action, err)
109109
}
110-
handlerFn, err := router(event.Action, h)
110+
handlerFn, cfnErr := router(event.Action, h)
111111
log.Printf("Handler received the %s action", event.Action)
112-
if err != nil {
113-
return re.report(event, "router error", err, serviceInternalError)
112+
if cfnErr != nil {
113+
return re.report(event, "router error", cfnErr, serviceInternalError)
114114
}
115115
if err := validateEvent(event); err != nil {
116116
return re.report(event, "validation error", err, invalidRequestError)
@@ -158,7 +158,7 @@ func scrubFiles(dir string) error {
158158

159159
// router decides which handler should be invoked based on the action
160160
// It will return a route or an error depending on the action passed in
161-
func router(a string, h Handler) (handlerFunc, error) {
161+
func router(a string, h Handler) (handlerFunc, cfnerr.Error) {
162162
// Figure out which action was called and have a "catch-all"
163163
switch a {
164164
case createAction:
@@ -185,7 +185,7 @@ func invoke(handlerFn handlerFunc, request handler.Request, metricsPublisher *me
185185

186186
// Ask the goroutine to do some work for us.
187187
go func() {
188-
//start the timer
188+
// start the timer
189189
s := time.Now()
190190
metricsPublisher.PublishInvocationMetric(time.Now(), string(action))
191191

cfn/cfnerr/types.go

+17-1
Original file line numberDiff line numberDiff line change
@@ -118,11 +118,15 @@ func (b baseError) OrigErrs() []error {
118118

119119
// So that the Error interface type can be included as an anonymous field
120120
// in the requestError struct and not conflict with the error.Error() method.
121+
//
122+
//nolint:all
121123
type cfnError Error
122124

123125
// A requestError wraps a request or service error.
124126
//
125127
// Composed of baseError for code, message, and original error.
128+
//
129+
//nolint:all
126130
type requestError struct {
127131
cfnError
128132
statusCode int
@@ -137,6 +141,8 @@ type requestError struct {
137141
// that may be meaningful.
138142
//
139143
// Also wraps original errors via the baseError.
144+
//
145+
//nolint:all
140146
func newRequestError(err Error, statusCode int, requestID string) *requestError {
141147
return &requestError{
142148
cfnError: err,
@@ -147,6 +153,8 @@ func newRequestError(err Error, statusCode int, requestID string) *requestError
147153

148154
// Error returns the string representation of the error.
149155
// Satisfies the error interface.
156+
//
157+
//nolint:all
150158
func (r requestError) Error() string {
151159
extra := fmt.Sprintf("status code: %d, request id: %s",
152160
r.statusCode, r.requestID)
@@ -155,22 +163,30 @@ func (r requestError) Error() string {
155163

156164
// String returns the string representation of the error.
157165
// Alias for Error to satisfy the stringer interface.
166+
//
167+
//nolint:all
158168
func (r requestError) String() string {
159169
return r.Error()
160170
}
161171

162172
// StatusCode returns the wrapped status code for the error
173+
//
174+
//nolint:all
163175
func (r requestError) StatusCode() int {
164176
return r.statusCode
165177
}
166178

167179
// RequestID returns the wrapped requestID
180+
//
181+
//nolint:all
168182
func (r requestError) RequestID() string {
169183
return r.requestID
170184
}
171185

172186
// OrigErrs returns the original errors if one was set. An empty slice is
173187
// returned if no error was set.
188+
//
189+
//nolint:all
174190
func (r requestError) OrigErrs() []error {
175191
if b, ok := r.cfnError.(BatchedErrors); ok {
176192
return b.OrigErrs()
@@ -189,7 +205,7 @@ func (e errorList) Error() string {
189205
// How do we want to handle the array size being zero
190206
if size := len(e); size > 0 {
191207
for i := 0; i < size; i++ {
192-
msg += fmt.Sprintf("%s", e[i].Error())
208+
msg += e[i].Error()
193209
// We check the next index to see if it is within the slice.
194210
// If it is, then we append a newline. We do this, because unit tests
195211
// could be broken with the additional '\n'

cfn/context.go

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ func GetContextSession(ctx context.Context) (*session.Session, error) {
5353

5454
// marshalCallback allows for a handler.ProgressEvent to be parsed into something
5555
// the RPDK can use to reinvoke the resource provider with the same context.
56+
//
57+
//nolint:all
5658
func marshalCallback(pevt *handler.ProgressEvent) (map[string]interface{}, int64) {
5759
return map[string]interface{}(pevt.CallbackContext), pevt.CallbackDelaySeconds
5860
}

cfn/entry_test.go

+1-4
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import (
66
"os"
77
"path/filepath"
88
"testing"
9-
10-
"github.com/aws-cloudformation/cloudformation-cli-go-plugin/cfn/cfnerr"
119
)
1210

1311
func TestMarshalling(t *testing.T) {
@@ -69,8 +67,7 @@ func TestRouter(t *testing.T) {
6967

7068
t.Run("Failed Path", func(t *testing.T) {
7169
fn, err := router(unknownAction, &EmptyHandler{})
72-
cfnErr := err.(cfnerr.Error)
73-
if cfnErr != nil && cfnErr.Code() != invalidRequestError {
70+
if err != nil && err.Code() != invalidRequestError {
7471
t.Errorf("Unspecified error returned: %v", err)
7572
} else if err == nil {
7673
t.Errorf("There should have been an error")

cfn/event.go

+2
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ func validateEvent(event *event) error {
5151

5252
// resourceHandlerRequest is internal to the RPDK. It contains a number of fields that are for
5353
// internal contract testing use only.
54+
//
55+
//nolint:all
5456
type resourceHandlerRequest struct {
5557
ClientRequestToken string `json:"clientRequestToken"`
5658
DesiredResourceState json.RawMessage `json:"desiredResourceState"`

cfn/handler/event.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ type ProgressEvent struct {
1515
HandlerErrorCode string `json:"errorCode,omitempty"`
1616

1717
// Message which can be shown to callers to indicate the
18-
//nature of a progress transition or callback delay; for example a message
19-
//indicating "propagating to edge."
18+
// nature of a progress transition or callback delay; for example a message
19+
// indicating "propagating to edge."
2020
Message string `json:"message,omitempty"`
2121

2222
// CallbackContext is an arbitrary datum which the handler can return in an

cfn/handler/handler_test.go

+3-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package handler
33
import (
44
"testing"
55

6-
"github.com/aws-cloudformation/cloudformation-cli-go-plugin/cfn/cfnerr"
76
"github.com/aws/aws-sdk-go/aws"
87
)
98

@@ -54,8 +53,7 @@ func TestNewRequest(t *testing.T) {
5453
t.Fatalf("Didn't throw an error")
5554
}
5655

57-
cfnErr := err.(cfnerr.Error)
58-
if cfnErr.Code() != bodyEmptyError {
56+
if err.Code() != bodyEmptyError {
5957
t.Fatalf("Wrong error returned: %v", err)
6058
}
6159
})
@@ -70,8 +68,7 @@ func TestNewRequest(t *testing.T) {
7068
t.Fatalf("Didn't throw an error")
7169
}
7270

73-
cfnErr := err.(cfnerr.Error)
74-
if cfnErr.Code() != marshalingError {
71+
if err.Code() != marshalingError {
7572
t.Fatalf("Wrong error returned: %v", err)
7673
}
7774
})
@@ -88,8 +85,7 @@ func TestNewRequest(t *testing.T) {
8885
t.Fatalf("Didn't throw an error")
8986
}
9087

91-
cfnErr := err.(cfnerr.Error)
92-
if cfnErr.Code() != marshalingError {
88+
if err.Code() != marshalingError {
9389
t.Fatalf("Wrong error returned: %v", err)
9490
}
9591
})

cfn/handler/request.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func NewRequest(id string, ctx map[string]interface{}, requestCTX RequestContext
7676

7777
// UnmarshalPrevious populates the provided interface
7878
// with the previous properties of the resource
79-
func (r *Request) UnmarshalPrevious(v interface{}) error {
79+
func (r *Request) UnmarshalPrevious(v interface{}) cfnerr.Error {
8080
if len(r.previousResourcePropertiesBody) == 0 {
8181
return nil
8282
}
@@ -90,7 +90,7 @@ func (r *Request) UnmarshalPrevious(v interface{}) error {
9090

9191
// Unmarshal populates the provided interface
9292
// with the current properties of the resource
93-
func (r *Request) Unmarshal(v interface{}) error {
93+
func (r *Request) Unmarshal(v interface{}) cfnerr.Error {
9494
if len(r.resourcePropertiesBody) == 0 {
9595
return cfnerr.New(bodyEmptyError, "Body is empty", nil)
9696
}

cfn/metrics/publisher.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,19 @@ import (
1616
const (
1717
// MetricNameSpaceRoot is the Metric name space root.
1818
MetricNameSpaceRoot = "AWS/CloudFormation"
19-
//MetricNameHanderException is a metric type.
19+
// MetricNameHanderException is a metric type.
2020
MetricNameHanderException = "HandlerException"
21-
//MetricNameHanderDuration is a metric type.
21+
// MetricNameHanderDuration is a metric type.
2222
MetricNameHanderDuration = "HandlerInvocationDuration"
23-
//MetricNameHanderInvocationCount is a metric type.
23+
// MetricNameHanderInvocationCount is a metric type.
2424
MetricNameHanderInvocationCount = "HandlerInvocationCount"
25-
//DimensionKeyAcionType is the Action key in the dimension.
25+
// DimensionKeyAcionType is the Action key in the dimension.
2626
DimensionKeyAcionType = "Action"
27-
//DimensionKeyExceptionType is the ExceptionType in the dimension.
27+
// DimensionKeyExceptionType is the ExceptionType in the dimension.
2828
DimensionKeyExceptionType = "ExceptionType"
29-
//DimensionKeyResourceType is the ResourceType in the dimension.
29+
// DimensionKeyResourceType is the ResourceType in the dimension.
3030
DimensionKeyResourceType = "ResourceType"
31-
//ServiceInternalError ...
31+
// ServiceInternalError ...
3232
ServiceInternalError string = "ServiceInternal"
3333
)
3434

0 commit comments

Comments
 (0)