diff --git a/.github/workflows/adr-accepted.yml b/.github/workflows/adr-accepted.yml index bfe151ff4..4f933e5e6 100644 --- a/.github/workflows/adr-accepted.yml +++ b/.github/workflows/adr-accepted.yml @@ -1,18 +1,86 @@ name: ADR accepted + on: issues: types: - closed -jobs: - main: - name: ADR accepted - runs-on: ubuntu-latest +permissions: + contents: read +jobs: + accept: + runs-on: ubuntu-latest steps: - - name: memorialize the ADR - uses: 18F/adr-automation/accepted@actioning + + - name: check for tags + if: "${{ !contains(github.event.issue.labels.*.name, 'ADR: accepted' )}}" + shell: bash + run: exit 0 + + - name: checkout main branch + uses: actions/checkout@v3 + with: + ref: main with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - label: "ADR: accepted" - path: docs/adrs + ssh-key: ${{ secrets.SSH_PRIVATE_KEY }} + + - name: get ADR number + id: next + shell: bash + run: | + mkdir -p docs/adrs + LAST_ADR=$(ls docs/adrs/*.md | grep -Eo "/[0-9]+-" | sort | tail -n1 | grep -Eo "[0-9]+") + LAST_ADR=$(echo "$LAST_ADR" | sed -E 's/^0+//') + NEXT_ADR=$(($LAST_ADR + 1)) + NEXT_ADR=$(printf "%04i" "$NEXT_ADR") + echo "number=$NEXT_ADR" >> "$GITHUB_OUTPUT" + + - name: get date + id: date + shell: bash + run: echo "date=$(date +'%B %d, %Y')" >> "$GITHUB_OUTPUT" + + - name: build filename + id: filename + shell: bash + run: | + SLUG=$(printf '%q\n' "${{ github.event.issue.title }}" | tr A-Z a-z) + SLUG=$(printf '%q\n' "$SLUG" | iconv -c -t ascii//TRANSLIT) + SLUG=$(printf '%q\n' "$SLUG" | sed -E 's/[^a-z0-9]+/-/g' | sed -E 's/-+/-/g' | sed -E 's/^-+|-+$//g') + + FILENAME="docs/adrs/${{ steps.next.outputs.number }}-$SLUG.md" + echo "slug=$SLUG" >> "$GITHUB_OUTPUT" + echo "filename=$FILENAME" >> "$GITHUB_OUTPUT" + + - name: write the ADR + uses: DamianReeves/write-file-action@v1.2 + with: + path: ${{ steps.filename.outputs.filename }} + write-mode: overwrite + contents: | + # ${{ github.event.issue.title }} + + Status: Accepted + Date: ${{ steps.date.outputs.date }} + + ${{ github.event.issue.body }} + + - name: branch, commit, and open PR + shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + BRANCH="adr/auto/${{ steps.filename.outputs.slug }}" + git config --global user.email "tts@gsa.gov" + git config --global user.name "Notify ADR Automation" + git checkout -b $BRANCH + git add docs/adrs/*.md + git commit -m "add ADR ${{ steps.next.outputs.number }}: ${{ github.event.issue.title }}" + git push -f origin $BRANCH + gh pr create \ + --title "Add ADR ${{ steps.next.outputs.number }} to the repo" \ + --body "This pull request was opened automatically because #${{ github.event.issue.number }} was closed after being marked as an approved ADR. It contains a markdown file capturing the ADR body at the time the issue was closed. Please verify that the markdown is correct before merging!" || true + gh pr merge $BRANCH --auto --squash || true + + \ No newline at end of file diff --git a/README.md b/README.md index eb68b03f8..35396711f 100644 --- a/README.md +++ b/README.md @@ -100,53 +100,55 @@ A direct installation of PostgreSQL will not put the `createdb` command on your ## Documentation -- [Infrastructure overview](#infrastructure-overview) - - [GitHub Repositories](#github-repositories) - - [Terraform](#terraform) - - [AWS](#aws) - - [New Relic](#new-relic) - - [Onboarding](#onboarding) - - [Setting up the infrastructure](#setting-up-the-infrastructure) -- [Testing](#testing) - - [CI testing](#ci-testing) - - [Manual testing](#manual-testing) - - [To run a local OWASP scan](#to-run-a-local-owasp-scan) -- [Deploying](#deploying) - - [Egress Proxy](#egress-proxy) - - [Sandbox environment](#sandbox-environment) -- [Database management](#database-management) - - [Initial state](#initial-state) - - [Data Model Diagram](#data-model-diagram) - - [Migrations](#migrations) - - [Purging user data](#purging-user-data) -- [One-off tasks](#one-off-tasks) -- [How messages are queued and sent](#how-messages-are-queued-and-sent) -- [Writing public APIs](#writing-public-apis) - - [Overview](#overview) - - [Documenting APIs](#documenting-apis) - - [New APIs](#new-apis) -- [API Usage](#api-usage) - - [Connecting to the API](#connecting-to-the-api) - - [Postman Documentation](#postman-documentation) - - [Using OpenAPI documentation](#using-openapi-documentation) -- [Queues and tasks](#queues-and-tasks) - - [Priority queue](#priority-queue) - - [Celery scheduled tasks](#celery-scheduled-tasks) -- [US Notify](#us-notify) - - [System Description](#system-description) -- [Run Book](#run-book) - - [ Alerts, Notifications, Monitoring](#-alerts-notifications-monitoring) - - [ Restaging Apps](#-restaging-apps) - - [ Smoke-testing the App](#-smoke-testing-the-app) - - [ Configuration Management](#-configuration-management) - - [ DNS Changes](#-dns-changes) - - [Exporting test results for compliance monitoring](#exporting-test-results-for-compliance-monitoring) - - [ Known Gotchas](#-known-gotchas) - - [ User Account Management](#-user-account-management) - - [ SMS Phone Number Management](#-sms-phone-number-management) -- [Data Storage Policies \& Procedures](#data-storage-policies--procedures) - - [Potential PII Locations](#potential-pii-locations) - - [Data Retention Policy](#data-retention-policy) +- [Infrastructure overview](./docs/all.md#infrastructure-overview) + - [GitHub Repositories](./docs/all.md#github-repositories) + - [Terraform](./docs/all.md#terraform) + - [AWS](./docs/all.md#aws) + - [New Relic](./docs/all.md#new-relic) + - [Onboarding](./docs/all.md#onboarding) + - [Setting up the infrastructure](./docs/all.md#setting-up-the-infrastructure) +- [Using the logs](./docs/all.md#using-the-logs) +- [Testing](./docs/all.md#testing) + - [CI testing](./docs/all.md#ci-testing) + - [Manual testing](./docs/all.md#manual-testing) + - [To run a local OWASP scan](./docs/all.md#to-run-a-local-owasp-scan) +- [Deploying](./docs/all.md#deploying) + - [Egress Proxy](./docs/all.md#egress-proxy) + - [Managing environment variables](./docs/all.md#managing-environment-variables) + - [Sandbox environment](./docs/all.md#sandbox-environment) +- [Database management](./docs/all.md#database-management) + - [Initial state](./docs/all.md#initial-state) + - [Data Model Diagram](./docs/all.md#data-model-diagram) + - [Migrations](./docs/all.md#migrations) + - [Purging user data](./docs/all.md#purging-user-data) +- [One-off tasks](./docs/all.md#one-off-tasks) +- [How messages are queued and sent](./docs/all.md#how-messages-are-queued-and-sent) +- [Writing public APIs](./docs/all.md#writing-public-apis) + - [Overview](./docs/all.md#overview) + - [Documenting APIs](./docs/all.md#documenting-apis) + - [New APIs](./docs/all.md#new-apis) +- [API Usage](./docs/all.md#api-usage) + - [Connecting to the API](./docs/all.md#connecting-to-the-api) + - [Postman Documentation](./docs/all.md#postman-documentation) + - [Using OpenAPI documentation](./docs/all.md#using-openapi-documentation) +- [Queues and tasks](./docs/all.md#queues-and-tasks) + - [Priority queue](./docs/all.md#priority-queue) + - [Celery scheduled tasks](./docs/all.md#celery-scheduled-tasks) +- [US Notify](./docs/all.md#us-notify) + - [System Description](./docs/all.md#system-description) +- [Run Book](./docs/all.md#run-book) + - [ Alerts, Notifications, Monitoring](./docs/all.md#-alerts-notifications-monitoring) + - [ Restaging Apps](./docs/all.md#-restaging-apps) + - [ Smoke-testing the App](./docs/all.md#-smoke-testing-the-app) + - [ Configuration Management](./docs/all.md#-configuration-management) + - [ DNS Changes](./docs/all.md#-dns-changes) + - [Exporting test results for compliance monitoring](./docs/all.md#exporting-test-results-for-compliance-monitoring) + - [ Known Gotchas](./docs/all.md#-known-gotchas) + - [ User Account Management](./docs/all.md#-user-account-management) + - [ SMS Phone Number Management](./docs/all.md#-sms-phone-number-management) +- [Data Storage Policies \& Procedures](./docs/all.md#data-storage-policies--procedures) + - [Potential PII Locations](./docs/all.md#potential-pii-locations) + - [Data Retention Policy](./docs/all.md#data-retention-policy) ## License && public domain diff --git a/app/celery/tasks.py b/app/celery/tasks.py index 31aee0dd6..b46637099 100644 --- a/app/celery/tasks.py +++ b/app/celery/tasks.py @@ -193,6 +193,12 @@ def save_sms(self, service_id, notification_id, encrypted_notification, sender_i return try: + job_id = notification.get("job", None) + created_by_id = None + if job_id: + job = dao_get_job_by_id(job_id) + created_by_id = job.created_by_id + saved_notification = persist_notification( template_id=notification["template"], template_version=notification["template_version"], @@ -203,6 +209,7 @@ def save_sms(self, service_id, notification_id, encrypted_notification, sender_i api_key_id=None, key_type=KEY_TYPE_NORMAL, created_at=datetime.utcnow(), + created_by_id=created_by_id, job_id=notification.get("job", None), job_row_number=notification.get("row_number", None), notification_id=notification_id, diff --git a/app/clients/cloudwatch/aws_cloudwatch.py b/app/clients/cloudwatch/aws_cloudwatch.py index f9eef87d4..3447cbc20 100644 --- a/app/clients/cloudwatch/aws_cloudwatch.py +++ b/app/clients/cloudwatch/aws_cloudwatch.py @@ -4,6 +4,7 @@ import re import time from boto3 import client +from flask import current_app from app.clients import AWS_CLIENT_CONFIG, Client from app.cloudfoundry_config import cloud_config @@ -50,6 +51,7 @@ class AwsCloudwatchClient(Client): # Check all cloudwatch logs from the time the notification was sent (currently 5 minutes previously) until now now = round(time.time() * 1000) beginning = sent_at + current_app.logger.info(f"TIME RANGE TO CHECK {beginning} to {now}") next_token = None all_log_events = [] while True: @@ -72,13 +74,20 @@ class AwsCloudwatchClient(Client): all_log_events.extend(log_events) if len(log_events) > 0: # We found it + current_app.logger.info( + f"WE FOUND THE EVENT WE WERE LOOKING FOR? {log_events}" + ) break next_token = response.get("nextToken") if not next_token: break + if len(all_log_events) == 0: + print(f"WE FOUND NO LOG EVENTS OVER TIME RANGE {beginning} to {now}") return all_log_events def check_sms(self, message_id, notification_id, created_at): + if os.getenv("LOCALSTACK_ENDPOINT_URL"): + current_app.logger.info("GADZOOKS WE ARE RUNNING WITH LOCALSTACK") region = cloud_config.sns_region # TODO this clumsy approach to getting the account number will be fixed as part of notify-api #258 account_number = cloud_config.ses_domain_arn @@ -87,24 +96,39 @@ class AwsCloudwatchClient(Client): account_number = account_number[0] log_group_name = f"sns/{region}/{account_number}/DirectPublishToPhoneNumber" + current_app.logger.info( + f"LOG GROUP NAME: {log_group_name} MESSAGE ID: {message_id}" + ) filter_pattern = '{$.notification.messageId="XXXXX"}' filter_pattern = filter_pattern.replace("XXXXX", message_id) all_log_events = self._get_log(filter_pattern, log_group_name, created_at) + current_app.logger.info(f"NUMBER OF ALL LOG EVENTS {len(all_log_events)}") if all_log_events and len(all_log_events) > 0: + current_app.logger.info( + "SHOULD RETURN SUCCESS BECAUSE WE FOUND A SUCCESS MESSAGE FOR MESSAGE ID" + ) event = all_log_events[0] message = json.loads(event["message"]) + current_app.logger.info(f"MESSAGE {message}") return "success", message["delivery"]["providerResponse"] log_group_name = ( f"sns/{region}/{account_number}/DirectPublishToPhoneNumber/Failure" ) + current_app.logger.info(f"FAILURE LOG GROUP NAME {log_group_name}") all_failed_events = self._get_log(filter_pattern, log_group_name, created_at) + current_app.logger.info( + f"NUMBER OF ALL FAILED LOG EVENTS {len(all_failed_events)}" + ) if all_failed_events and len(all_failed_events) > 0: + current_app.logger.info("SHOULD RETURN FAILED BECAUSE WE FOUND A FAILURE") event = all_failed_events[0] message = json.loads(event["message"]) + current_app.logger.info(f"MESSAGE {message}") return "failure", message["delivery"]["providerResponse"] + print(f"RAISING EXCEPTION FOR MESSAGE_ID {message_id}") raise Exception( f"No event found for message_id {message_id} notification_id {notification_id}" ) diff --git a/docs/all.md b/docs/all.md index 10134db31..276fa649d 100644 --- a/docs/all.md +++ b/docs/all.md @@ -5,12 +5,14 @@ - [New Relic](#new-relic) - [Onboarding](#onboarding) - [Setting up the infrastructure](#setting-up-the-infrastructure) +- [Using the logs](#using-the-logs) - [Testing](#testing) - [CI testing](#ci-testing) - [Manual testing](#manual-testing) - [To run a local OWASP scan](#to-run-a-local-owasp-scan) - [Deploying](#deploying) - [Egress Proxy](#egress-proxy) + - [Managing environment variables](#managing-environment-variables) - [Sandbox environment](#sandbox-environment) - [Database management](#database-management) - [Initial state](#initial-state) @@ -85,13 +87,17 @@ In addition to terraform directories in the api and admin apps above: ## Terraform +We use Terraform to manage our infrastructure, providing consistent setups across the environments. + +Our Terraform configurations manage components via cloud.gov. This means that the configurations should work out of the box if you are using a Cloud Foundry platform, but will not work for setups based on raw AWS. + ### Development There are several remote services required for local development: -* s3 -* ses -* sns +* S3 +* SES +* SNS Credentials for these services are created by running: @@ -205,6 +211,20 @@ Example answers for toll-free registration form ![example answers for toll-free registration form](./toll-free-registration.png) +# Using the logs + +If you're using the `cf` CLI, you can run `cf logs notify-api-ENV` and/or `cf logs notify-admin-ENV` to stream logs in real time. Add `--recent` to get the last few logs, though logs often move pretty quickly. + +For general log searching, [the cloud.gov Kibana instance](https://logs.fr.cloud.gov/) is powerful, though quite complex to get started. For shortcuts to errors, some team members have New Relic access. + +The links below will open a filtered view with logs from both applications, which can then be filtered further. However, for the links to work, you need to paste them into the URL bar while *already* logged into and viewing the Kibana page. If not, you'll just be redirected to the generic dashboard. + +Production: https://logs.fr.cloud.gov/app/discover#/view/218a6790-596d-11ee-a43a-090d426b9a38 +Demo: https://logs.fr.cloud.gov/app/discover#/view/891392a0-596e-11ee-921a-1b6b2f4d89ed +Staging: https://logs.fr.cloud.gov/app/discover#/view/73d7c820-596e-11ee-a43a-090d426b9a38 + +Once in the view, you'll likely want to adjust the time range in the upper right of the page. + # Testing ``` @@ -304,6 +324,26 @@ application to a select list of allowed domains. Update the allowed domains by updating `deploy-config/egress_proxy/notify-api-.allow.acl` and deploying an updated version of the application throught he normal deploy process. +## Managing environment variables + +For an environment variable to make its way into the cloud.gov environment, it *must* end up in the `manifest.yml` file. Based on the deployment approach described above, there are 2 ways for this to happen. + +### Secret environment variables + +Because secrets are pulled from GitHub, they must be passed from our action to the deploy action and then placed into `manifest.yml`. This means that they should be in a 4 places: + +- [ ] The GitHub secrets store +- [ ] The deploy action in the `env` section using the format `{secrets.SECRET_NAME}` +- [ ] The deploy action in the `push_arguments` section using the format `--var SECRET_NAME="$SECRET_NAME"` +- [ ] The manifest using the format `SECRET_NAME: ((SECRET_NAME))` + +### Public environment variables + +Public env vars make up the configuration in `deploy-config`. These are pulled in together by the `--vars-file` line in the deploy action. To add or update one, it should be in 2 places: + +- [ ] The relevant YAML file in `deploy-config` using the format `var_name: value` +- [ ] The manifest using the format `((var_name))` + ## Sandbox environment There is a sandbox space, complete with terraform and `deploy-config/sandbox.yml` file available diff --git a/poetry.lock b/poetry.lock index ac0df2c2a..0b289a1c4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -309,33 +309,33 @@ files = [ [[package]] name = "black" -version = "23.7.0" +version = "23.9.1" description = "The uncompromising code formatter." optional = false python-versions = ">=3.8" files = [ - {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"}, - {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"}, - {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"}, - {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"}, - {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"}, - {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"}, - {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"}, - {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"}, - {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"}, - {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"}, - {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"}, - {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"}, - {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"}, - {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"}, - {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"}, - {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"}, - {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"}, - {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"}, - {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"}, - {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"}, - {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"}, - {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"}, + {file = "black-23.9.1-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:d6bc09188020c9ac2555a498949401ab35bb6bf76d4e0f8ee251694664df6301"}, + {file = "black-23.9.1-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:13ef033794029b85dfea8032c9d3b92b42b526f1ff4bf13b2182ce4e917f5100"}, + {file = "black-23.9.1-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:75a2dc41b183d4872d3a500d2b9c9016e67ed95738a3624f4751a0cb4818fe71"}, + {file = "black-23.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13a2e4a93bb8ca74a749b6974925c27219bb3df4d42fc45e948a5d9feb5122b7"}, + {file = "black-23.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:adc3e4442eef57f99b5590b245a328aad19c99552e0bdc7f0b04db6656debd80"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:8431445bf62d2a914b541da7ab3e2b4f3bc052d2ccbf157ebad18ea126efb91f"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:8fc1ddcf83f996247505db6b715294eba56ea9372e107fd54963c7553f2b6dfe"}, + {file = "black-23.9.1-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:7d30ec46de88091e4316b17ae58bbbfc12b2de05e069030f6b747dfc649ad186"}, + {file = "black-23.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:031e8c69f3d3b09e1aa471a926a1eeb0b9071f80b17689a655f7885ac9325a6f"}, + {file = "black-23.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:538efb451cd50f43aba394e9ec7ad55a37598faae3348d723b59ea8e91616300"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:638619a559280de0c2aa4d76f504891c9860bb8fa214267358f0a20f27c12948"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:a732b82747235e0542c03bf352c126052c0fbc458d8a239a94701175b17d4855"}, + {file = "black-23.9.1-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:cf3a4d00e4cdb6734b64bf23cd4341421e8953615cba6b3670453737a72ec204"}, + {file = "black-23.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cf99f3de8b3273a8317681d8194ea222f10e0133a24a7548c73ce44ea1679377"}, + {file = "black-23.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:14f04c990259576acd093871e7e9b14918eb28f1866f91968ff5524293f9c573"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:c619f063c2d68f19b2d7270f4cf3192cb81c9ec5bc5ba02df91471d0b88c4c5c"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:6a3b50e4b93f43b34a9d3ef00d9b6728b4a722c997c99ab09102fd5efdb88325"}, + {file = "black-23.9.1-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:c46767e8df1b7beefb0899c4a95fb43058fa8500b6db144f4ff3ca38eb2f6393"}, + {file = "black-23.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50254ebfa56aa46a9fdd5d651f9637485068a1adf42270148cd101cdf56e0ad9"}, + {file = "black-23.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:403397c033adbc45c2bd41747da1f7fc7eaa44efbee256b53842470d4ac5a70f"}, + {file = "black-23.9.1-py3-none-any.whl", hash = "sha256:6ccd59584cc834b6d127628713e4b6b968e5f79572da66284532525a042549f9"}, + {file = "black-23.9.1.tar.gz", hash = "sha256:24b6b3ff5c6d9ea08a8888f6977eae858e1f340d7260cf56d70a49823236b62d"}, ] [package.dependencies] @@ -345,7 +345,7 @@ packaging = ">=22.0" pathspec = ">=0.9.0" platformdirs = ">=2" tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} -typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} +typing-extensions = {version = ">=4.0.1", markers = "python_version < \"3.11\""} [package.extras] colorama = ["colorama (>=0.4.3)"] @@ -1386,20 +1386,20 @@ smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.36" +version = "3.1.37" description = "GitPython is a Python library used to interact with Git repositories" optional = false python-versions = ">=3.7" files = [ - {file = "GitPython-3.1.36-py3-none-any.whl", hash = "sha256:8d22b5cfefd17c79914226982bb7851d6ade47545b1735a9d010a2a4c26d8388"}, - {file = "GitPython-3.1.36.tar.gz", hash = "sha256:4bb0c2a6995e85064140d31a33289aa5dce80133a23d36fcd372d716c54d3ebf"}, + {file = "GitPython-3.1.37-py3-none-any.whl", hash = "sha256:5f4c4187de49616d710a77e98ddf17b4782060a1788df441846bddefbb89ab33"}, + {file = "GitPython-3.1.37.tar.gz", hash = "sha256:f9b9ddc0761c125d5780eab2d64be4873fc6817c2899cbcb34b02344bdc7bc54"}, ] [package.dependencies] gitdb = ">=4.0.1,<5" [package.extras] -test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-sugar", "virtualenv"] +test = ["black", "coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mypy", "pre-commit", "pytest", "pytest-cov", "pytest-sugar"] [[package]] name = "govuk-bank-holidays" @@ -2044,16 +2044,6 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, - {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -2455,7 +2445,7 @@ smartypants = ">=2.0.1" type = "git" url = "https://github.com/GSA/notifications-utils.git" reference = "main" -resolved_reference = "d3ad5b127a257f52f6dc36fe555a4b9c980c16b3" +resolved_reference = "5eadd38702fd187fd2954a5c763314b9b2446bea" [[package]] name = "numpy" @@ -3842,13 +3832,13 @@ files = [ [[package]] name = "types-pyyaml" -version = "6.0.12.11" +version = "6.0.12.12" description = "Typing stubs for PyYAML" optional = false python-versions = "*" files = [ - {file = "types-PyYAML-6.0.12.11.tar.gz", hash = "sha256:7d340b19ca28cddfdba438ee638cd4084bde213e501a3978738543e27094775b"}, - {file = "types_PyYAML-6.0.12.11-py3-none-any.whl", hash = "sha256:a461508f3096d1d5810ec5ab95d7eeecb651f3a15b71959999988942063bf01d"}, + {file = "types-PyYAML-6.0.12.12.tar.gz", hash = "sha256:334373d392fde0fdf95af5c3f1661885fa10c52167b14593eb856289e1855062"}, + {file = "types_PyYAML-6.0.12.12-py3-none-any.whl", hash = "sha256:c05bc6c158facb0676674b7f11fe3960db4f389718e19e62bd2b84d6205cfd24"}, ] [[package]] @@ -4291,4 +4281,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "642319df54dfc549b650ff145855594e79d21c6191af06c85632595feef13482" +content-hash = "15aafd504a605f6621f3017ddfba898373885f90926eb16eef363ba5b33b53a6" diff --git a/pyproject.toml b/pyproject.toml index 4f088b097..1e91acf7e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ asn1crypto = "==1.5.1" async-timeout = "==4.0.2" attrs = "==23.1.0" awscli = "==1.29.15" -black = "==23.7.0" +black = "==23.9.1" bcrypt = "==3.2.2" beautifulsoup4 = "==4.12.2" billiard = "==3.6.4.0"