gh actions works (#149)

This commit is contained in:
Will Freeman
2026-08-22 21:30:38 -06:00
committed by GitHub
parent 74a09421dc
commit e124d28c8e
6 changed files with 98 additions and 30 deletions
+37
View File
@@ -0,0 +1,37 @@
name: ALPR Counts Deploy
on:
push:
branches: [master]
paths:
- 'serverless/alpr_counts/**'
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-1
- name: Login to ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2
- name: Build and push image
working-directory: serverless/alpr_counts/src
run: |
docker buildx build --platform linux/arm64 \
-t ${{ steps.login-ecr.outputs.registry }}/alpr_counts-lambda:latest --load .
docker push ${{ steps.login-ecr.outputs.registry }}/alpr_counts-lambda:latest
- name: Update Lambda function code
run: |
aws lambda update-function-code \
--function-name alpr_counts \
--image-uri ${{ steps.login-ecr.outputs.registry }}/alpr_counts-lambda:latest
+5 -1
View File
@@ -3,4 +3,8 @@
Counts total ALPRs reported in the OSM database, hourly. OSM's Overpass API is used to query for counts of all ALPRs and ALPRs in the United States. The counts are stored in a JSON file in an S3 bucket.
## Deploying
This Lambda uses a zip file, so from the `/terraform` directory, you can run `terraform apply -target=module.alpr_counts` after making changes, and it should detect the changes, rebuild the zip, and update the Lambda's function code.
This Lambda runs as a container image. Code changes to `serverless/alpr_counts/**` deploy automatically via GitHub Actions (`.github/workflows/alpr-counts-deploy.yml`) on push to `master` — it builds the image, pushes it to ECR, and updates the Lambda's function code.
To deploy manually (e.g. for local testing), run `./deploy.sh` with AWS credentials configured.
Infrastructure changes (IAM, ECR repo, EventBridge schedule, alarms) still go through Terraform: from the `/terraform` directory, run `terraform apply -target=module.alpr_counts`.
+26
View File
@@ -0,0 +1,26 @@
#!/bin/bash
ECR_REPO_URL=912821578123.dkr.ecr.us-east-1.amazonaws.com/alpr_counts-lambda
set -e
# check if AWS role is assumed
if ! aws sts get-caller-identity &> /dev/null; then
echo "Error: AWS role is not assumed. Please assume the necessary role and try again."
exit 1
fi
cd src
# login to ECR
aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin $ECR_REPO_URL
# build and push Docker image to ECR for ARM64 using legacy format
docker buildx build --platform linux/arm64 -t $ECR_REPO_URL:latest --load .
docker push $ECR_REPO_URL:latest
# update lambda function
export AWS_PAGER=""
aws lambda update-function-code --function-name alpr_counts --image-uri $ECR_REPO_URL:latest
echo "Deployed!"
+12
View File
@@ -0,0 +1,12 @@
# Use the official AWS Lambda Python 3.13 base image from public ECR
FROM public.ecr.aws/lambda/python:3.13-arm64
# Copy function code
COPY alpr_counts.py ${LAMBDA_TASK_ROOT}
# Install dependencies
COPY requirements.txt .
RUN pip install -r requirements.txt
# Set the CMD to your handler
CMD ["alpr_counts.lambda_handler"]
+3 -2
View File
@@ -1,4 +1,5 @@
import json
import os
import requests
import boto3
from concurrent.futures import ThreadPoolExecutor, as_completed
@@ -76,8 +77,8 @@ def lambda_handler(event, context):
}
s3 = boto3.client('s3')
bucket = 'cdn.deflock.me'
key = 'alpr-counts.json'
bucket = os.environ['OUTPUT_BUCKET']
key = os.environ.get('OUTPUT_KEY', 'alpr-counts.json')
s3.put_object(
Bucket=bucket,
+15 -27
View File
@@ -39,36 +39,24 @@ resource "aws_iam_role_policy_attachment" "lambda_s3_write_attachment" {
policy_arn = aws_iam_policy.lambda_s3_write_policy.arn
}
resource "null_resource" "pip_install" {
provisioner "local-exec" {
command = <<EOT
cd ${path.root}/../serverless/${var.module_name}/src
pip3.14 install -r requirements.txt -t .
EOT
}
triggers = {
# Re-run the provisioner if the file changes
file_hash = "${filemd5("${path.root}/../serverless/${var.module_name}/src/${var.module_name}.py")}"
}
}
data "archive_file" "python_lambda_package" {
type = "zip"
source_dir = "${path.root}/../serverless/${var.module_name}/src"
output_path = "${path.root}/../serverless/${var.module_name}/lambda.zip"
depends_on = [ null_resource.pip_install ]
resource "aws_ecr_repository" "lambda_repository" {
name = "${var.module_name}-lambda"
}
resource "aws_lambda_function" "overpass_lambda" {
filename = data.archive_file.python_lambda_package.output_path
function_name = var.module_name
role = aws_iam_role.lambda_role.arn
handler = "${var.module_name}.lambda_handler"
runtime = "python3.14"
source_code_hash = data.archive_file.python_lambda_package.output_base64sha256
timeout = 180
function_name = var.module_name
role = aws_iam_role.lambda_role.arn
package_type = "Image"
image_uri = "${aws_ecr_repository.lambda_repository.repository_url}:latest"
timeout = 180
architectures = ["arm64"]
environment {
variables = {
OUTPUT_BUCKET = var.deflock_stats_bucket
OUTPUT_KEY = var.output_filename
}
}
}
resource "aws_cloudwatch_event_rule" "lambda_rule" {