Skip to content

Commit d1b0f89

Browse files
committed
Overhaul of lambda template to uv and updated devops conventions
Why these changes are being introduced: This overhaul of the lambda template has been percolating for some time, with changes like pipenv to uv, use of AWS SAM for testing, and some updates to how we run linting, pre-commit hooks, etc. This work is taken on together to bring a holistic upgrade to the template instead of piecemeal work that was entrenching some stale patterns. How this addresses that need: It was going to be difficult to break this work out into meaningful smaller commits, given how interwoven the changes are. The work breaks down into a few major areas: 1. Update from pipenv to uv 2. Introduce a Config class and simplify the lambda skeleton 3. Introduce AWS SAM for local testing 4. Update linting, pre-commit, and Makefile conventions While theoretically possible to commit those changes in order, it felt like an artifical divvying up of work. These changes have been vetted in other contexts independently; this commit weaves them together for this template repository. Side effects of this change: * uv nows used for python environment and dependencies * pre-commit only fires for git push, not git commit * security scanning is opt-in until renovate becomes a rolling dependency manager in CI Relevant ticket(s): * https://mitlibraries.atlassian.net/browse/IN-1542
1 parent aa33724 commit d1b0f89

18 files changed

+1397
-939
lines changed

.github/pull-request-template.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,15 @@ YES | NO
1515
### What are the relevant tickets?
1616
- Include links to Jira Software and/or Jira Service Management tickets here.
1717

18-
### Code review
19-
* Code review best practices are documented [here](https://mitlibraries.github.io/guides/collaboration/code_review.html) and you are encouraged to have a constructive dialogue with your reviewers about their preferences and expectations.
18+
### Developer
19+
- [ ] All new ENV is documented in README
20+
- [ ] All new ENV has been added to staging and production environments
21+
- [ ] All related Jira tickets are linked in commit message(s)
22+
- [ ] Stakeholder approval has been confirmed (or is not needed)
23+
24+
### Code Reviewer(s)
25+
- [ ] The commit message is clear and follows our guidelines (not just this PR message)
26+
- [ ] There are appropriate tests covering any new functionality
27+
- [ ] The provided documentation is sufficient for understanding any new functionality introduced
28+
- [ ] Any manual tests have been performed and verified
29+
- [ ] New dependencies are appropriate or there were no changes

.github/workflows/ci.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
name: CI
2-
on: push
2+
on:
3+
pull_request:
4+
paths-ignore:
5+
- '.github/**'
36
jobs:
47
test:
5-
uses: mitlibraries/.github/.github/workflows/python-shared-test.yml@main
8+
uses: mitlibraries/.github/.github/workflows/python-uv-shared-test.yml@main
69
lint:
7-
uses: mitlibraries/.github/.github/workflows/python-shared-lint.yml@main
10+
uses: mitlibraries/.github/.github/workflows/python-uv-shared-lint.yml@main

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,4 +136,7 @@ dmypy.json
136136
.vscode/
137137

138138
# jetbrains
139-
.idea/
139+
.idea/
140+
141+
.aws-sam/
142+
tests/sam/env.json

.pre-commit-config.yaml

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,28 @@
11
default_language_version:
2-
python: python3.12 # set for project python version
2+
python: python3.12
3+
default_stages:
4+
- pre-push
35
repos:
46
- repo: local
57
hooks:
6-
- id: black-apply
7-
name: black-apply
8-
entry: pipenv run black
8+
- id: ruff-format
9+
name: ruff-format
10+
entry: uv run ruff format --diff
911
language: system
1012
pass_filenames: true
11-
types: ["python"]
13+
types: [ "python" ]
14+
1215
- id: mypy
1316
name: mypy
14-
entry: pipenv run mypy
17+
entry: uv run mypy
1518
language: system
1619
pass_filenames: true
17-
types: ["python"]
18-
exclude: "tests/"
19-
- id: ruff-apply
20-
name: ruff-apply
21-
entry: pipenv run ruff check --fix
20+
types: [ "python" ]
21+
exclude: "(tests/|output/|migrations/)"
22+
23+
- id: ruff-check
24+
name: ruff-check
25+
entry: uv run ruff check
2226
language: system
2327
pass_filenames: true
24-
types: ["python"]
25-
- id: pip-audit
26-
name: pip-audit
27-
entry: pipenv run pip-audit
28-
language: system
29-
pass_filenames: false
28+
types: [ "python" ]

.python-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.12
1+
3.13

Dockerfile

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
FROM public.ecr.aws/lambda/python:3.12
1+
FROM public.ecr.aws/lambda/python:3.13
22

3-
# Copy function code
4-
COPY . ${LAMBDA_TASK_ROOT}/
3+
# Install uv
4+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
5+
6+
# Copy project metadata
7+
COPY pyproject.toml uv.lock* ./
58

69
# Install dependencies
7-
RUN pip3 install pipenv
8-
RUN pipenv requirements > requirements.txt
9-
RUN pip3 install -r requirements.txt --target "${LAMBDA_TASK_ROOT}"
10+
RUN cd ${LAMBDA_TASK_ROOT} && \
11+
uv export --format requirements-txt --no-hashes --no-dev > requirements.txt && \
12+
uv pip install -r requirements.txt --target "${LAMBDA_TASK_ROOT}" --system
13+
14+
# Copy project files
15+
COPY . ${LAMBDA_TASK_ROOT}/
1016

1117
# Default handler. See README for how to override to a different handler.
1218
CMD [ "lambdas.my_function.lambda_handler" ]

Makefile

Lines changed: 52 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,53 +5,75 @@ help: # Preview Makefile commands
55
@awk 'BEGIN { FS = ":.*#"; print "Usage: make <target>\n\nTargets:" } \
66
/^[-_[:alpha:]]+:.?*#/ { printf " %-15s%s\n", $$1, $$2 }' $(MAKEFILE_LIST)
77

8-
#######################
9-
# Dependency commands
10-
#######################
8+
# ensure OS binaries aren't called if naming conflict with Make recipes
9+
.PHONY: help install venv update test coveralls lint lint-fix security my-app
1110

12-
install: # Install Python dependencies
13-
pipenv install --dev
14-
pipenv run pre-commit install
11+
##############################################
12+
# Python Environment and Dependency commands
13+
##############################################
1514

16-
update: install # Update Python dependencies
17-
pipenv clean
18-
pipenv update --dev
15+
install: .venv .git/hooks/pre-commit .git/hooks/pre-push # Install Python dependencies and create virtual environment if not exists
16+
uv sync --dev
17+
18+
.venv: # Creates virtual environment if not found
19+
@echo "Creating virtual environment at .venv..."
20+
uv venv .venv
21+
22+
.git/hooks/pre-commit: # Sets up pre-commit commit hooks if not setup
23+
@echo "Installing pre-commit commit hooks..."
24+
uv run pre-commit install --hook-type pre-commit
25+
26+
.git/hooks/pre-push: # Sets up pre-commit push hooks if not setup
27+
@echo "Installing pre-commit push hooks..."
28+
uv run pre-commit install --hook-type pre-push
29+
30+
venv: .venv # Create the Python virtual environment
31+
32+
update: # Update Python dependencies
33+
uv lock --upgrade
34+
uv sync --dev
1935

2036
######################
2137
# Unit test commands
2238
######################
2339

2440
test: # Run tests and print a coverage report
25-
pipenv run coverage run --source=lambdas -m pytest -vv
26-
pipenv run coverage report -m
41+
uv run coverage run --source=lambdas -m pytest -vv
42+
uv run coverage report -m
2743

2844
coveralls: test # Write coverage data to an LCOV report
29-
pipenv run coverage lcov -o ./coverage/lcov.info
45+
uv run coverage lcov -o ./coverage/lcov.info
3046

3147
####################################
32-
# Code quality and safety commands
48+
# Code linting and formatting
3349
####################################
3450

35-
lint: black mypy ruff safety # Run linters
36-
37-
black: # Run 'black' linter and print a preview of suggested changes
38-
pipenv run black --check --diff .
51+
lint: # Run linting, alerts only, no code changes
52+
uv run ruff format --diff
53+
uv run mypy .
54+
uv run ruff check .
3955

40-
mypy: # Run 'mypy' linter
41-
pipenv run mypy .
56+
lint-fix: # Run linting, auto fix behaviors where supported
57+
uv run ruff format .
58+
uv run ruff check --fix .
4259

43-
ruff: # Run 'ruff' linter and print a preview of errors
44-
pipenv run ruff check .
60+
security: # Run security / vulnerability checks
61+
uv run pip-audit
4562

46-
safety: # Check for security vulnerabilities and verify Pipfile.lock is up-to-date
47-
pipenv run pip-audit
48-
pipenv verify
63+
####################################
64+
# SAM Lambda
65+
####################################
66+
sam-build: # SAM: Build SAM image for running Lambda locally
67+
sam build --template tests/sam/template.yaml
4968

50-
lint-apply: # Apply changes with 'black' and resolve 'fixable errors' with 'ruff'
51-
black-apply ruff-apply
69+
sam-http-run: # SAM: Run lambda locally as an HTTP server
70+
sam local start-api --template tests/sam/template.yaml --env-vars tests/sam/env.json
5271

53-
black-apply: # Apply changes with 'black'
54-
pipenv run black .
72+
sam-http-ping: # SAM: Send curl command to SAM HTTP server
73+
curl --location 'http://localhost:3000/myapp' \
74+
--header 'Content-Type: application/json' \
75+
--data '{"msg":"in a bottle"}'
5576

56-
ruff-apply: # Resolve 'fixable errors' with 'ruff'
57-
pipenv run ruff check --fix .
77+
sam-invoke: # SAM: Invoke lambda directly
78+
echo '{"msg":"in a bottle"}' \
79+
| sam local invoke -e -

Pipfile

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)