Skip to content

Commit d2675ec

Browse files
authored
feat: add lint and unit test workflow checks for pull requests (#152)
1 parent 333a9f2 commit d2675ec

26 files changed

+1442
-392
lines changed

.github/workflows/unit-test.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,15 @@ jobs:
3131
run: |
3232
python -m pip install --upgrade pip
3333
python -m pip install pipenv
34+
35+
- name: Install local deps
36+
run: pipenv install --dev
37+
38+
- name: Lint check
39+
run: pipenv run lint:ci
40+
41+
- name: Type check
42+
run: pipenv run typecheck
43+
44+
- name: Unit tests
45+
run: pipenv run test

.gitignore

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,59 @@ override.tf.json
2828
.terraformrc
2929
terraform.rc
3030

31+
# Locals
32+
.swp
33+
.idea
34+
.idea*
35+
.vscode/*
36+
*.DS_Store
37+
*.zip
38+
.env
39+
.envrc
40+
41+
# Byte-compiled / optimized / DLL files
42+
__pycache__/
43+
*.py[cod]
44+
*$py.class
45+
46+
# Distribution / packaging
47+
.Python
48+
env/
49+
build/
50+
develop-eggs/
51+
dist/
52+
downloads/
53+
eggs/
54+
.eggs/
55+
lib/
56+
lib64/
57+
parts/
58+
sdist/
59+
var/
60+
*.egg-info/
61+
.installed.cfg
62+
*.egg
63+
64+
# Unit test / coverage reports
65+
.pytest*
66+
htmlcov/
67+
.tox/
68+
.coverage
69+
.coverage.*
70+
.cache
71+
nosetests.xml
72+
coverage.xml
73+
*.cover
74+
*.coverage
75+
.hypothesis/
76+
.mypy_cache/
77+
78+
# Lockfile
79+
Pipfile.lock
80+
3181
# Lambda directories
3282
builds/
33-
__pycache__/
3483
functions/pytest.ini
35-
*.zip
84+
85+
# Integration testing file
86+
.int.env

README.md

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,11 @@ Doing serverless with Terraform? Check out [serverless.tf framework](https://ser
1212
- Create new SNS topic or use existing one
1313
- Support plaintext and encrypted version of Slack webhook URL
1414
- Most of Slack message options are customizable
15-
- Support different types of SNS messages:
15+
- Various event types are supported, even generic messages:
1616
- AWS CloudWatch Alarms
1717
- AWS CloudWatch LogMetrics Alarms
1818
- AWS GuardDuty Findings
19-
- Local pytest driven testing of the lambda to a Slack sandbox channel
2019

21-
## Feature Roadmap
22-
23-
- More SNS message types: [Send pull-request to add support of other message types](https://github.com/terraform-aws-modules/terraform-aws-notify-slack/pulls)
2420

2521
## Usage
2622

@@ -37,10 +33,6 @@ module "notify_slack" {
3733
}
3834
```
3935

40-
## Upgrade from 2.0 to 3.0
41-
42-
Version 3 uses [Terraform AWS Lambda module](https://github.com/terraform-aws-modules/terraform-aws-lambda) to handle most of heavy-lifting related to Lambda packaging, roles, and permissions, while maintaining the same interface for the user of this module after many of resources will be recreated.
43-
4436
## Using with Terraform Cloud Agents
4537

4638
[Terraform Cloud Agents](https://www.terraform.io/docs/cloud/workspaces/agent.html) are a paid feature, available as part of the Terraform Cloud for Business upgrade package.
@@ -62,18 +54,9 @@ If you want to subscribe the AWS Lambda Function created by this module to an ex
6254
- [notify-slack-simple](https://github.com/terraform-aws-modules/terraform-aws-notify-slack/tree/master/examples/notify-slack-simple) - Creates SNS topic which sends messages to Slack channel.
6355
- [cloudwatch-alerts-to-slack](https://github.com/terraform-aws-modules/terraform-aws-notify-slack/tree/master/examples/cloudwatch-alerts-to-slack) - End to end example which shows how to send AWS Cloudwatch alerts to Slack channel and use KMS to encrypt webhook URL.
6456

65-
## Testing with pytest
66-
67-
To run the tests:
68-
69-
1. Set up a dedicated slack channel as a test sandbox with it's own webhook. See [Slack Incoming Webhooks docs](https://api.slack.com/messaging/webhooks) for details.
70-
2. Make a copy of the sample pytest configuration and edit as needed.
71-
72-
cp functions/pytest.ini.sample functions/pytest.ini
73-
74-
3. Run the tests:
57+
## Local Development and Testing
7558

76-
pytest functions/notify_slack_test.py
59+
See the [functions](https://github.com/terraform-aws-modules/terraform-aws-notify-slack/tree/master/functions) for further details.
7760

7861
<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
7962
## Requirements

examples/notify-slack-simple/README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,14 @@ Note that this example may create resources which can cost money (AWS Elastic IP
2525
|------|---------|
2626
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 0.13.1 |
2727
| <a name="requirement_aws"></a> [aws](#requirement\_aws) | >= 3.61 |
28+
| <a name="requirement_local"></a> [local](#requirement\_local) | >= 2.0 |
2829

2930
## Providers
3031

3132
| Name | Version |
3233
|------|---------|
3334
| <a name="provider_aws"></a> [aws](#provider\_aws) | >= 3.61 |
35+
| <a name="provider_local"></a> [local](#provider\_local) | >= 2.0 |
3436

3537
## Modules
3638

@@ -42,7 +44,8 @@ Note that this example may create resources which can cost money (AWS Elastic IP
4244

4345
| Name | Type |
4446
|------|------|
45-
| [aws_sns_topic.my_sns](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource |
47+
| [aws_sns_topic.example](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sns_topic) | resource |
48+
| [local_file.integration_testing](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource |
4649

4750
## Inputs
4851

examples/notify-slack-simple/main.tf

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,52 @@
11
provider "aws" {
2+
region = local.region
3+
}
4+
5+
locals {
6+
name = "ex-${replace(basename(path.cwd), "_", "-")}"
27
region = "eu-west-1"
8+
tags = {
9+
Owner = "user"
10+
Environment = "dev"
11+
}
312
}
413

5-
resource "aws_sns_topic" "my_sns" {
6-
name = "my-sns"
14+
################################################################################
15+
# Supporting Resources
16+
################################################################################
17+
18+
resource "aws_sns_topic" "example" {
19+
name = local.name
20+
tags = local.tags
721
}
822

23+
################################################################################
24+
# Slack Notify Module
25+
################################################################################
26+
927
module "notify_slack" {
1028
source = "../../"
1129

12-
sns_topic_name = aws_sns_topic.my_sns.name
30+
sns_topic_name = aws_sns_topic.example.name
1331
create_sns_topic = false
1432

1533
slack_webhook_url = "https://hooks.slack.com/services/AAA/BBB/CCC"
1634
slack_channel = "aws-notification"
1735
slack_username = "reporter"
1836

19-
tags = {
20-
Name = "notify-slack-simple"
21-
}
37+
tags = local.tags
38+
}
39+
40+
################################################################################
41+
# Integration Testing Support
42+
# This populates a file that is gitignored to aid in executing the integration tests locally
43+
################################################################################
2244

23-
depends_on = [aws_sns_topic.my_sns]
45+
resource "local_file" "integration_testing" {
46+
filename = "${path.module}/../../functions/.int.env"
47+
content = <<-EOT
48+
REGION=${local.region}
49+
LAMBDA_FUNCTION_NAME=${module.notify_slack.notify_slack_lambda_function_name}
50+
SNS_TOPIC_ARN=${aws_sns_topic.example.arn}
51+
EOT
2452
}

examples/notify-slack-simple/versions.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,9 @@ terraform {
66
source = "hashicorp/aws"
77
version = ">= 3.61"
88
}
9+
local = {
10+
source = "hashicorp/local"
11+
version = ">= 2.0"
12+
}
913
}
1014
}

functions/.flake8

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[flake8]
2+
max-complexity = 10
3+
max-line-length = 120
4+
exclude =
5+
.pytest_cache
6+
__pycache__/
7+
*tests/
8+
events/
9+
messages/
10+
snapshots/

functions/.pyproject.toml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
[tool.black]
2+
line-length = 120
3+
target-version = ['py38']
4+
include = '\.pyi?$'
5+
verbose = true
6+
exclude = '''
7+
/(
8+
| \.git
9+
| \.mypy_cache
10+
| dist
11+
| \.pants\.d
12+
| virtualenvs
13+
| \.venv
14+
| _build
15+
| build
16+
| dist
17+
| snapshots
18+
)/
19+
'''
20+
21+
[tool.isort]
22+
line_length = 120
23+
skip = '.terraform'
24+
sections = 'FUTURE,STDLIB,THIRDPARTY,FIRSTPARTY,LOCALFOLDER'
25+
known_third_party = 'aws_lambda_powertools,boto3,botocore,pytest,snapshottest'
26+
known_first_party = 'events,notify_slack'
27+
indent = ' '
28+
29+
[tool.mypy]
30+
namespace_packages = true
31+
explicit_package_bases = true
32+
33+
no_implicit_optional = true
34+
implicit_reexport = false
35+
strict_equality = true
36+
37+
warn_unused_configs = true
38+
warn_unused_ignores = true
39+
warn_return_any = true
40+
warn_redundant_casts = true
41+
warn_unreachable = true
42+
43+
pretty = true
44+
show_column_numbers = true
45+
show_error_context = true
46+
show_error_codes = true
47+
show_traceback = true
48+
49+
[tool.coverage.run]
50+
branch = true
51+
omit = ["*_test.py", "tests/*", "events/*", "messages/*", "snapshots/*", "venv/*", ".mypy_cache/*", ".pytest_cache/*"]
52+
53+
[tool.coverage.report]
54+
show_missing = true
55+
skip_covered = true
56+
skip_empty = true
57+
sort = "-Miss"
58+
fail_under = 75

functions/Pipfile

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
[[source]]
2+
url = "https://pypi.org/simple"
3+
verify_ssl = true
4+
name = "pypi"
5+
6+
[packages]
7+
8+
[dev-packages]
9+
boto3 = "~=1.20"
10+
botocore = "~=1.23"
11+
black = "*"
12+
flake8 = "*"
13+
isort = "*"
14+
mypy = "*"
15+
pytest = "*"
16+
pytest-cov = "*"
17+
radon = "*"
18+
snapshottest = "~=0.6"
19+
20+
[requires]
21+
python_version = "3.8"
22+
23+
[scripts]
24+
test = "python3 -m pytest --cov --cov-report=term"
25+
'test:updatesnapshots' = "python3 -m pytest --snapshot-update"
26+
cover = "python3 -m coverage html"
27+
complexity = "python3 -m radon cc notify_slack.py -a"
28+
halstead = "python3 -m radon hal notify_slack.py"
29+
typecheck = "python3 -m mypy . --ignore-missing-imports"
30+
lint = "python3 -m flake8 . --count --statistics --benchmark --exit-zero --config=.flake8"
31+
'lint:ci' = "python3 -m flake8 . --config=.flake8"
32+
imports = "python3 -m isort . --profile black"
33+
format = "python3 -m black ."
34+
35+
[pipenv]
36+
allow_prereleases = true

0 commit comments

Comments
 (0)