Skip to content

Commit 7a890b4

Browse files
authored
Merge branch 'api-keys' into api_key_v2
2 parents 8b41263 + 0d81699 commit 7a890b4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+268
-534
lines changed

.bumpversion.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 0.4.6
2+
current_version = 0.4.7
33
commit = False
44
tag = False
55

.github/workflows/ci.yaml

+5-2
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,13 @@ jobs:
5858
docker build -t delphi_web_epidata -f ./devops/Dockerfile .
5959
cd ../../../
6060
61+
# MODULE_NAME specifies the location of the `app` variable, the actual WSGI application object to run.
62+
# see https://github.com/tiangolo/meinheld-gunicorn-docker#module_name
6163
- name: Start services
6264
run: |
6365
docker network create --driver bridge delphi-net
6466
docker run --rm -d -p 13306:3306 --network delphi-net --name delphi_database_epidata --cap-add=sys_nice delphi_database_epidata
65-
docker run --rm -d -p 10080:80 --env "SQLALCHEMY_DATABASE_URI=mysql+mysqldb://user:pass@delphi_database_epidata:3306/epidata" --env "FLASK_SECRET=abc" --env "FLASK_PREFIX=/epidata" --env "RATELIMIT_STORAGE_URL=redis://delphi_redis_instance:6379" --env "API_KEY_REGISTER_WEBHOOK_TOKEN=abc" --env "API_KEY_ADMIN_PASSWORD=test_admin_password" --network delphi-net --name delphi_web_epidata delphi_web_epidata
67+
docker run --rm -d -p 10080:80 --env "MODULE_NAME=delphi.epidata.server.main" --env "SQLALCHEMY_DATABASE_URI=mysql+mysqldb://user:pass@delphi_database_epidata:3306/epidata" --env "FLASK_SECRET=abc" --env "FLASK_PREFIX=/epidata" --env "RATELIMIT_STORAGE_URL=redis://delphi_redis_instance:6379" --env "API_KEY_REGISTER_WEBHOOK_TOKEN=abc" --env "API_KEY_ADMIN_PASSWORD=test_admin_password" --network delphi-net --name delphi_web_epidata delphi_web_epidata
6668
docker run --rm -p 6379:6379 --network delphi-net --name delphi_redis_instance delphi_redis_instance
6769
docker ps
6870
@@ -108,7 +110,8 @@ jobs:
108110
image:
109111
needs: build
110112
# only on main and dev branch
111-
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev'
113+
# TODO: #1112 Remove `|| github.ref == 'refs/heads/api-keys'` after transition to production status.
114+
if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/dev' || github.ref == 'refs/heads/api-keys'
112115

113116
runs-on: ubuntu-latest
114117
steps:

.github/workflows/performance-tests.yml

+82-6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ jobs:
1515
# Make sure 1. this is a PR, not an issue 2. it contains "/run performance test" anywhere in the body
1616
if: github.event.issue.pull_request && contains(github.event.comment.body, '/run performance test')
1717
runs-on: ubuntu-latest
18+
outputs:
19+
request_count: ${{ steps.output.outputs.request_count }}
20+
failure_count: ${{ steps.output.outputs.failure_count }}
21+
med_time: ${{ steps.output.outputs.med_time }}
22+
avg_time: ${{ steps.output.outputs.avg_time }}
23+
min_time: ${{ steps.output.outputs.min_time }}
24+
max_time: ${{ steps.output.outputs.max_time }}
25+
requests_per_sec: ${{ steps.output.outputs.requests_per_sec }}
1826
steps:
1927
- name: Set up WireGuard
2028
uses: egor-tensin/[email protected]
@@ -52,19 +60,60 @@ jobs:
5260
run: |
5361
cd ../driver
5462
sudo make web sql="${{ secrets.DB_CONN_STRING }}"
63+
- name: Check out delphi-admin
64+
uses: actions/checkout@v3
65+
with:
66+
repository: cmu-delphi/delphi-admin
67+
token: ${{ secrets.CMU_DELPHI_DEPLOY_MACHINE_PAT }}
68+
path: delphi-admin
5569
- name: Build & run Locust
70+
continue-on-error: true # sometimes ~2-5 queries fail, we shouldn't end the run if that's the case
5671
run: |
57-
cd ../driver/repos/delphi/delphi-epidata/tests/performance
72+
cd delphi-admin/load-testing/locust
5873
docker build -t locust .
59-
docker run --net=host -v $PWD:/mnt/locust -e CSV=/mnt/locust/v4-requests-smaller.csv locust -f /mnt/locust/v4.py --host http://127.0.0.1:10080/ --users 10 --spawn-rate 1 --headless -t 15m
74+
export CSV=v4-requests-as_of.csv
75+
touch output_stats.csv && chmod 666 output_stats.csv
76+
touch output_stats_history.csv && chmod 666 output_stats_history.csv
77+
touch output_failures.csv && chmod 666 output_failures.csv
78+
touch output_exceptions.csv && chmod 666 output_exceptions.csv
79+
docker run --net=host -v $PWD:/mnt/locust -e CSV="/mnt/locust/${CSV}" locust -f /mnt/locust/v4.py --host http://127.0.0.1:10080/ --users 10 --spawn-rate 1 --headless -i "$(cat ${CSV} | wc -l)" --csv=/mnt/locust/output
80+
- name: Produce output for summary
81+
id: output
82+
uses: jannekem/run-python-script-action@v1
83+
with:
84+
script: |
85+
import os
86+
87+
def write_string(name, value):
88+
with open(os.environ['GITHUB_OUTPUT'], 'a') as fh:
89+
print(f'{name}={value}', file=fh)
90+
91+
def write_float(name, value):
92+
write_string(name, "{:.2f}".format(float(value)))
6093
61-
comment-output:
94+
with open("delphi-admin/load-testing/locust/output_stats.csv", "r", encoding="utf-8", errors="ignore") as scraped:
95+
final_line = scraped.readlines()[-1].split(",")
96+
write_string('request_count', final_line[2])
97+
write_string('failure_count', final_line[3])
98+
write_float('med_time', final_line[4])
99+
write_float('avg_time', final_line[5])
100+
write_float('min_time', final_line[6])
101+
write_float('max_time', final_line[7])
102+
write_float('requests_per_sec', final_line[9])
103+
104+
- name: Archive results as artifacts
105+
uses: actions/upload-artifact@v3
106+
with:
107+
name: locust-output
108+
path: |
109+
delphi-admin/load-testing/locust/output_*.csv
110+
111+
comment-success:
62112
runs-on: ubuntu-latest
63-
if: success() || failure() # but not if skipped
113+
if: success()
64114
needs: run-perftests
65115
steps:
66116
- name: Comment run results
67-
# URL that links to run results
68117
env:
69118
GITHUB_WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
70119
uses: actions/github-script@v5
@@ -75,6 +124,33 @@ jobs:
75124
issue_number: context.issue.number,
76125
owner: context.repo.owner,
77126
repo: context.repo.repo,
78-
body: '✅ Performance tests complete! Click here to view results: ${{ env.GITHUB_WORKFLOW_URL }}'
127+
body: `✅ Performance tests complete! Result summary:
128+
- Total requests: **${{ needs.run-perftests.outputs.request_count }}**
129+
- Total failures: **${{ needs.run-perftests.outputs.failure_count }}**
130+
- Min response time: **${{ needs.run-perftests.outputs.min_time }} ms**
131+
- Max response time: **${{ needs.run-perftests.outputs.max_time }} ms**
132+
- Average response time: **${{ needs.run-perftests.outputs.avg_time }} ms**
133+
- Median response time: **${{ needs.run-perftests.outputs.med_time }} ms**
134+
- Requests per second: **${{ needs.run-perftests.outputs.requests_per_sec }}**
135+
136+
Click here to view full results: ${{ env.GITHUB_WORKFLOW_URL }}.`
79137
})
80138
139+
comment-failure:
140+
runs-on: ubuntu-latest
141+
if: failure()
142+
needs: run-perftests
143+
steps:
144+
- name: Comment run results
145+
env:
146+
GITHUB_WORKFLOW_URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
147+
uses: actions/github-script@v5
148+
with:
149+
github-token: ${{secrets.GITHUB_TOKEN}}
150+
script: |
151+
github.rest.issues.createComment({
152+
issue_number: context.issue.number,
153+
owner: context.repo.owner,
154+
repo: context.repo.repo,
155+
body: `❌ Performance tests failed! Click here to view full results: ${{ env.GITHUB_WORKFLOW_URL }}.`
156+
})

deploy.json

+16
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@
1717
"add-header-comment": true
1818
},
1919

20+
"// common",
21+
{
22+
"type": "move",
23+
"src": "src/common/",
24+
"dst": "[[package]]/common/",
25+
"match": "^.*\\.(py)$",
26+
"add-header-comment": true
27+
},
28+
2029
"// server",
2130
{
2231
"type": "move",
@@ -25,6 +34,13 @@
2534
"match": "^.*\\.(py)$",
2635
"add-header-comment": true
2736
},
37+
{
38+
"type": "move",
39+
"src": "src/server/utils",
40+
"dst": "[[package]]/server/utils/",
41+
"match": "^.*\\.(py)$",
42+
"add-header-comment": true
43+
},
2844
{
2945
"type": "move",
3046
"src": "src/server/endpoints",

dev/local/Makefile

+3
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,11 @@ web:
9191
cd -
9292

9393
@# Run the web server
94+
@# MODULE_NAME specifies the location of the `app` variable, the actual WSGI application object to run.
95+
@# see https://github.com/tiangolo/meinheld-gunicorn-docker#module_name
9496
@docker run --rm -p 127.0.0.1:10080:80 \
9597
$(M1) \
98+
--env "MODULE_NAME=delphi.epidata.server.main" \
9699
--env "SQLALCHEMY_DATABASE_URI=$(sqlalchemy_uri)" \
97100
--env "FLASK_SECRET=abc" --env "FLASK_PREFIX=/epidata" --env "LOG_DEBUG" \
98101
--network delphi-net --name delphi_web_epidata \

dev/local/setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[metadata]
22
name = Delphi Development
3-
version = 0.4.6
3+
version = 0.4.7
44

55
[options]
66
packages =

devops/Dockerfile

+6-4
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,16 @@ LABEL org.opencontainers.image.source=https://github.com/cmu-delphi/delphi-epida
88

99
COPY ./devops/gunicorn_conf.py /app
1010
COPY ./devops/start_wrapper.sh /
11-
COPY ./src/server/ /app/app/
12-
COPY --from=builder ./src/build/lib/ /app/app/lib/
11+
RUN mkdir -p /app/delphi/epidata
12+
COPY ./src/server /app/delphi/epidata/server
13+
COPY ./src/common /app/delphi/epidata/common
14+
COPY --from=builder ./src/build/lib/ /app/delphi/epidata/lib/
1315

1416
COPY requirements.api.txt /app/requirements_also.txt
1517

1618
RUN ln -s -f /usr/share/zoneinfo/America/New_York /etc/localtime \
17-
&& rm -rf /app/app/__pycache__ /app/app/*.php \
18-
&& chmod -R o+r /app/app \
19+
&& rm -rf /app/delphi/epidata/__pycache__ \
20+
&& chmod -R o+r /app/delphi/epidata \
1921
&& chmod 755 /start_wrapper.sh \
2022
&& pip install --no-cache-dir -r /tmp/requirements.txt -r requirements_also.txt
2123
# the file /tmp/requirements.txt is created in the parent docker definition. (see:

docs/symptom-survey/publications.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,14 @@ Pandemic"](https://www.pnas.org/topic/548) in *PNAS*:
2626

2727
Research publications using the survey data include:
2828

29+
- Taube JC, Susswein Z, Bansal S (2023). [Spatiotemporal Trends in Self-Reported
30+
Mask-Wearing Behavior in the United States: Analysis of a Large
31+
Cross-sectional Survey](https://doi.org/10.2196/42128). *JMIR Public Health
32+
and Surveillance* 9:e42128.
2933
- Rebecca L. Weintraub et al (2023). [Identifying COVID-19 Vaccine Deserts and
3034
Ways to Reduce Them: A Digital Tool to Support Public Health
3135
Decision-Making](https://doi.org/10.2105/AJPH.2022.307198). *American Journal
32-
of Public Health*.
36+
of Public Health* 113 (4), 363-367.
3337
- Anzalone AJ, Sun J, Vinson AJ, Beasley WH, Hillegass WB, Murray K, et al.
3438
(2023). [Community risks for SARS-CoV-2 infection among fully vaccinated US
3539
adults by rurality: A retrospective cohort study from the National COVID
@@ -38,7 +42,7 @@ Research publications using the survey data include:
3842
- Rufino, J., Baquero, C., Frey, D. et al (2023). [Using survey data to estimate
3943
the impact of the omicron variant on vaccine efficacy against COVID-19
4044
infection](https://doi.org/10.1038/s41598-023-27951-3). *Scientific Reports*
41-
13, 900 (2023).
45+
13, 900.
4246
- Rader, B., Astley, C.M., Sewalk, K. et al (2022). [Spatial modeling of vaccine
4347
deserts as barriers to controlling
4448
SARS-CoV-2](https://doi.org/10.1038/s43856-022-00183-8). *Communications

integrations/acquisition/covid_hosp/facility/test_scenarios.py

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ def setUp(self):
3939
with Database.connect() as db:
4040
with db.new_cursor() as cur:
4141
cur.execute('truncate table covid_hosp_facility')
42+
cur.execute('truncate table covid_hosp_facility_key')
4243
cur.execute('truncate table covid_hosp_meta')
4344
cur.execute('delete from api_user')
4445
cur.execute('insert into api_user(api_key, tracking, registered) values ("key", 1, 1)')

integrations/server/test_covidcast_endpoints.py

-26
Original file line numberDiff line numberDiff line change
@@ -183,32 +183,6 @@ def match_row(trend, row):
183183
self.assertEqual(trend["max_value"], first.value)
184184
self.assertEqual(trend["max_trend"], "decreasing")
185185

186-
def test_correlation(self):
187-
"""Request a signal from the /correlation endpoint."""
188-
189-
num_rows = 30
190-
reference_rows = [CovidcastTestRow.make_default_row(signal="ref", time_value=20200401 + i, value=i) for i in range(num_rows)]
191-
first = reference_rows[0]
192-
self._insert_rows(reference_rows)
193-
other_rows = [CovidcastTestRow.make_default_row(signal="other", time_value=20200401 + i, value=i) for i in range(num_rows)]
194-
other = other_rows[0]
195-
self._insert_rows(other_rows)
196-
max_lag = 3
197-
198-
out = self._fetch("/correlation", reference=first.signal_pair(), others=other.signal_pair(), geo=first.geo_pair(), window="20200401-20201212", lag=max_lag)
199-
self.assertEqual(out["result"], 1)
200-
df = pd.DataFrame(out["epidata"])
201-
self.assertEqual(len(df), max_lag * 2 + 1) # -...0...+
202-
self.assertEqual(df["geo_type"].unique().tolist(), [first.geo_type])
203-
self.assertEqual(df["geo_value"].unique().tolist(), [first.geo_value])
204-
self.assertEqual(df["signal_source"].unique().tolist(), [other.source])
205-
self.assertEqual(df["signal_signal"].unique().tolist(), [other.signal])
206-
207-
self.assertEqual(df["lag"].tolist(), list(range(-max_lag, max_lag + 1)))
208-
self.assertEqual(df["r2"].unique().tolist(), [1.0])
209-
self.assertEqual(df["slope"].unique().tolist(), [1.0])
210-
self.assertEqual(df["intercept"].tolist(), [3.0, 2.0, 1.0, 0.0, -1.0, -2.0, -3.0])
211-
self.assertEqual(df["samples"].tolist(), [num_rows - abs(l) for l in range(-max_lag, max_lag + 1)])
212186

213187
def test_csv(self):
214188
"""Request a signal from the /csv endpoint."""

0 commit comments

Comments
 (0)