Skip to content

Commit 4ed8f0a

Browse files
authored
Merge pull request #3 from cisagov/first-commits
Initial implementation
2 parents 1768884 + a0036c7 commit 4ed8f0a

26 files changed

+773
-5
lines changed

.bandit.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,4 @@ tests:
1010
# - B102
1111

1212
skips:
13-
# - B101 # skip "assert used" check since assertions are required in pytests
13+
- B101 # skip "assert used" check since assertions are required in pytests

.github/dependabot.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ updates:
1919
- dependency-name: actions/setup-python
2020
- dependency-name: hashicorp/setup-terraform
2121
- dependency-name: mxschmitt/action-tmate
22+
# Managed by cisagov/skeleton-aws-lambda-python
23+
# - dependency-name: actions/upload-artifact
2224

2325
- package-ecosystem: "pip"
2426
directory: "/"

.github/workflows/build.yml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ on:
99

1010
env:
1111
CURL_CACHE_DIR: ~/.cache/curl
12+
DEFAULT_ARTIFACT_NAME: lambda_build.zip
1213
PIP_CACHE_DIR: ~/.cache/pip
1314
PRE_COMMIT_CACHE_DIR: ~/.cache/pre-commit
1415
RUN_TMATE: ${{ secrets.RUN_TMATE }}
@@ -98,3 +99,71 @@ jobs:
9899
- name: Setup tmate debug session
99100
uses: mxschmitt/action-tmate@v3
100101
if: env.RUN_TMATE
102+
test:
103+
runs-on: ubuntu-latest
104+
needs: lint
105+
steps:
106+
- id: setup-env
107+
uses: cisagov/setup-env-github-action@develop
108+
- uses: actions/checkout@v3
109+
- id: setup-python
110+
uses: actions/setup-python@v4
111+
with:
112+
python-version: "3.10"
113+
- uses: actions/cache@v3
114+
env:
115+
BASE_CACHE_KEY: "${{ github.job }}-${{ runner.os }}-\
116+
py${{ steps.setup-python.outputs.python-version }}-"
117+
with:
118+
path: |
119+
${{ env.PIP_CACHE_DIR }}
120+
key: "${{ env.BASE_CACHE_KEY }}\
121+
${{ hashFiles('**/requirements-test.txt') }}-\
122+
${{ hashFiles('**/requirements.txt') }}"
123+
restore-keys: |
124+
${{ env.BASE_CACHE_KEY }}
125+
- name: Install dependencies
126+
run: |
127+
python -m pip install --upgrade pip
128+
pip install --upgrade --requirement requirements-test.txt
129+
- name: Run tests
130+
env:
131+
GITHUB_RELEASE_TAG: ${{ github.event.release.tag_name }}
132+
run: pytest
133+
- name: Setup tmate debug session
134+
uses: mxschmitt/action-tmate@v3
135+
if: env.RUN_TMATE
136+
build:
137+
runs-on: ubuntu-latest
138+
needs:
139+
- lint
140+
- test
141+
strategy:
142+
matrix:
143+
# Python runtime versions supported by AWS
144+
python-version:
145+
- "3.7"
146+
- "3.8"
147+
- "3.9"
148+
steps:
149+
- uses: actions/checkout@v3
150+
- name: Get the short SHA for the commit being used
151+
run: |
152+
echo "GH_SHORT_SHA=${GITHUB_SHA::7}" >> $GITHUB_ENV
153+
- name: Build the base Lambda Docker image
154+
run: |
155+
docker compose build \
156+
--build-arg PY_VERSION=${{ matrix.python-version }} \
157+
build_deployment_package
158+
- name: Generate the Lambda deployment package
159+
run: docker compose up build_deployment_package
160+
- name: Upload the generated Lambda deployment package as an artifact
161+
uses: actions/upload-artifact@v3
162+
with:
163+
name: "${{ github.event.repository.name }}-\
164+
py${{ matrix.python-version }}-\
165+
${{ env.GH_SHORT_SHA }}"
166+
path: "${{ env.DEFAULT_ARTIFACT_NAME }}"
167+
- name: Setup tmate debug session
168+
uses: mxschmitt/action-tmate@v3
169+
if: env.RUN_TMATE
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
---
2+
# For most projects, this workflow file will not need changing; you simply need
3+
# to commit it to your repository.
4+
#
5+
# You may wish to alter this file to override the set of languages analyzed,
6+
# or to provide custom queries or build logic.
7+
name: "CodeQL"
8+
9+
on:
10+
push:
11+
# Dependabot triggered push events have read-only access, but uploading code
12+
# scanning requires write access.
13+
branches-ignore:
14+
- dependabot/**
15+
pull_request:
16+
# The branches below must be a subset of the branches above
17+
branches:
18+
- develop
19+
schedule:
20+
- cron: '0 14 * * 6'
21+
22+
jobs:
23+
analyze:
24+
name: Analyze
25+
runs-on: ubuntu-latest
26+
permissions:
27+
# required for all workflows
28+
security-events: write
29+
strategy:
30+
fail-fast: false
31+
matrix:
32+
# Override automatic language detection by changing the below list
33+
# Supported options are go, javascript, csharp, python, cpp, and java
34+
language:
35+
- python
36+
# Learn more...
37+
# https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection
38+
39+
steps:
40+
- name: Checkout repository
41+
uses: actions/checkout@v3
42+
43+
# Initializes the CodeQL tools for scanning.
44+
- name: Initialize CodeQL
45+
uses: github/codeql-action/init@v2
46+
with:
47+
languages: ${{ matrix.language }}
48+
49+
# Autobuild attempts to build any compiled languages (C/C++, C#, or
50+
# Java). If this step fails, then you should remove it and run the build
51+
# manually (see below).
52+
- name: Autobuild
53+
uses: github/codeql-action/autobuild@v2
54+
55+
# ℹ️ Command-line programs to run using the OS shell.
56+
# 📚 https://git.io/JvXDl
57+
58+
# ✏️ If the Autobuild fails above, remove it and uncomment the following
59+
# three lines and modify them (or add more) to build your code if your
60+
# project uses a compiled language
61+
62+
# - run: |
63+
# make bootstrap
64+
# make release
65+
66+
- name: Perform CodeQL Analysis
67+
uses: github/codeql-action/analyze@v2

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
# Files already tracked by Git are not affected.
33
# See: https://git-scm.com/docs/gitignore
44

5+
## Project Specific ##
6+
lambda_build.zip
7+
58
## Python ##
69
__pycache__
710
.mypy_cache

.isort.cfg

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,7 @@ import_heading_stdlib=Standard Python Libraries
66
import_heading_thirdparty=Third-Party Libraries
77
import_heading_firstparty=cisagov Libraries
88

9+
known_first_party=example
10+
911
# Run isort under the black profile to align with our other Python linting
1012
profile=black

.pre-commit-config.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,22 @@ repos:
8181
- id: shell-lint
8282

8383
# Python hooks
84+
# Run bandit on the tests directory with a custom configuration
8485
- repo: https://github.com/PyCQA/bandit
8586
rev: 1.7.4
8687
hooks:
8788
- id: bandit
89+
name: bandit (tests directory)
90+
files: tests
8891
args:
8992
- --config=.bandit.yml
93+
# Run bandit on everything but the tests directory
94+
- repo: https://github.com/PyCQA/bandit
95+
rev: 1.7.4
96+
hooks:
97+
- id: bandit
98+
name: bandit (everything but the tests directory)
99+
exclude: tests
90100
- repo: https://github.com/psf/black
91101
rev: 22.10.0
92102
hooks:

Dockerfile

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
ARG PY_VERSION=3.9
2+
3+
FROM amazon/aws-lambda-python:$PY_VERSION as install-stage
4+
5+
# Declare it a second time so it's brought into this scope.
6+
ARG PY_VERSION=3.9
7+
8+
# Install the Python packages necessary to install the Lambda dependencies.
9+
RUN python3 -m pip install --no-cache-dir \
10+
pip \
11+
setuptools \
12+
wheel \
13+
# This version of pipenv is the minimum version to allow passing arguments
14+
# to pip with the --extra-pip-args option.
15+
&& python3 -m pip install --no-cache-dir "pipenv>=2022.9.8"
16+
17+
WORKDIR /tmp
18+
19+
# Copy in the dependency files.
20+
COPY src/py$PY_VERSION/ .
21+
22+
# Install the Lambda dependencies.
23+
#
24+
# The --extra-pip-args option is used to pass necessary arguments to the
25+
# underlying pip calls.
26+
RUN pipenv sync --system --extra-pip-args="--no-cache-dir --target ${LAMBDA_TASK_ROOT}"
27+
28+
FROM amazon/aws-lambda-python:$PY_VERSION as build-stage
29+
30+
###
31+
# For a list of pre-defined annotation keys and value types see:
32+
# https://github.com/opencontainers/image-spec/blob/master/annotations.md
33+
###
34+
# [email protected] is a very generic email distribution, and it is
35+
# unlikely that anyone on that distribution is familiar with the
36+
# particulars of your repository. It is therefore *strongly*
37+
# suggested that you use an email address here that is specific to the
38+
# person or group that maintains this repository; for example:
39+
# LABEL org.opencontainers.image.authors="[email protected]"
40+
LABEL org.opencontainers.image.authors="[email protected]"
41+
LABEL org.opencontainers.image.vendor="Cybersecurity and Infrastructure Security Agency"
42+
43+
# Declare it a third time so it's brought into this scope.
44+
ARG PY_VERSION=3.9
45+
46+
# This must be present in the image to generate a deployment artifact.
47+
ENV BUILD_PY_VERSION=$PY_VERSION
48+
49+
COPY --from=install-stage ${LAMBDA_TASK_ROOT} ${LAMBDA_TASK_ROOT}
50+
51+
WORKDIR ${LAMBDA_TASK_ROOT}
52+
53+
# Copy in the handler.
54+
COPY src/lambda_handler.py .
55+
56+
# Ensure our handler is invoked when the image is used.
57+
CMD ["lambda_handler.handler"]

README.md

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,74 @@
33
[![GitHub Build Status](https://github.com/cisagov/skeleton-aws-lambda-python/workflows/build/badge.svg)](https://github.com/cisagov/skeleton-aws-lambda-python/actions)
44

55
This is a generic skeleton project that can be used to quickly get a
6-
new [cisagov](https://github.com/cisagov) GitHub project started.
7-
This skeleton project contains [licensing information](LICENSE), as
6+
new [cisagov](https://github.com/cisagov) GitHub
7+
[AWS Lambda](https://aws.amazon.com/lambda/) project using the Python runtimes
8+
started. This skeleton project contains [licensing information](LICENSE), as
89
well as [pre-commit hooks](https://pre-commit.com) and
910
[GitHub Actions](https://github.com/features/actions) configurations
1011
appropriate for the major languages that we use.
1112

12-
In many cases you will instead want to use one of the more specific
13-
skeleton projects derived from this one.
13+
## Building the base Lambda image ##
14+
15+
The base Lambda image can be built with the following command:
16+
17+
```console
18+
docker compose build
19+
```
20+
21+
This base image is used both to build a deployment package and to run the
22+
Lambda locally.
23+
24+
## Building a deployment package ##
25+
26+
You can build a deployment zip file to use when creating a new AWS Lambda
27+
function with the following command:
28+
29+
```console
30+
docker compose up build_deployment_package
31+
```
32+
33+
This will output the deployment zip file in the root directory.
34+
35+
## Running the Lambda locally ##
36+
37+
The configuration in this repository allows you run the Lambda locally for
38+
testing as long as you do not need explicit permissions for other AWS
39+
services. This can be done with the following command:
40+
41+
```console
42+
docker compose up --detach run_lambda_locally
43+
```
44+
45+
You can then invoke the Lambda using the following:
46+
47+
```console
48+
curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
49+
```
50+
51+
The `{}` in the command is the invocation event payload to send to the Lambda
52+
and would be the value given as the `event` argument to the handler.
53+
54+
Once you are finished you can stop the detached container with the following command:
55+
56+
```console
57+
docker compose down
58+
```
59+
60+
## How to update Python dependencies ##
61+
62+
The Python dependencies are maintained using a [Pipenv](https://github.com/pypa/pipenv)
63+
configuration for each supported Python version. Changes to requirements
64+
should be made to the respective `src/py<Python version>/Pipfile`. More
65+
information about the `Pipfile` format can be found [here](https://pipenv.pypa.io/en/latest/basics/#example-pipfile-pipfile-lock).
66+
The accompanying `Pipfile.lock` files contain the specific dependency versions
67+
that will be installed. These files can be updated like so (using the Python
68+
3.9 configuration as an example):
69+
70+
```console
71+
cd src/py3.9
72+
pipenv lock
73+
```
1474

1575
## New Repositories from a Skeleton ##
1676

bump_version.sh

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/usr/bin/env bash
2+
3+
# bump_version.sh (show|major|minor|patch|prerelease|build)
4+
5+
set -o nounset
6+
set -o errexit
7+
set -o pipefail
8+
9+
VERSION_FILE=src/version.txt
10+
11+
HELP_INFORMATION="bump_version.sh (show|major|minor|patch|prerelease|build|finalize)"
12+
13+
old_version=$(sed -n "s/^__version__ = \"\(.*\)\"$/\1/p" $VERSION_FILE)
14+
# Comment out periods so they are interpreted as periods and don't
15+
# just match any character
16+
old_version_regex=${old_version//\./\\\.}
17+
18+
if [ $# -ne 1 ]; then
19+
echo "$HELP_INFORMATION"
20+
else
21+
case $1 in
22+
major | minor | patch | prerelease | build)
23+
new_version=$(python -c "import semver; print(semver.bump_$1('$old_version'))")
24+
echo Changing version from "$old_version" to "$new_version"
25+
# A temp file is used to provide compatability with macOS development
26+
# as a result of macOS using the BSD version of sed
27+
tmp_file=/tmp/version.$$
28+
sed "s/$old_version_regex/$new_version/" $VERSION_FILE > $tmp_file
29+
mv $tmp_file $VERSION_FILE
30+
git add $VERSION_FILE
31+
git commit -m"Bump version from $old_version to $new_version"
32+
git push
33+
;;
34+
finalize)
35+
new_version=$(python -c "import semver; print(semver.finalize_version('$old_version'))")
36+
echo Changing version from "$old_version" to "$new_version"
37+
# A temp file is used to provide compatability with macOS development
38+
# as a result of macOS using the BSD version of sed
39+
tmp_file=/tmp/version.$$
40+
sed "s/$old_version_regex/$new_version/" $VERSION_FILE > $tmp_file
41+
mv $tmp_file $VERSION_FILE
42+
git add $VERSION_FILE
43+
git commit -m"Finalize version from $old_version to $new_version"
44+
git push
45+
;;
46+
show)
47+
echo "$old_version"
48+
;;
49+
*)
50+
echo "$HELP_INFORMATION"
51+
;;
52+
esac
53+
fi

0 commit comments

Comments
 (0)