Skip to content

Commit 561087d

Browse files
authored
Merge branch 'dev' into add-repoint-api
2 parents b193fbe + d8d6ef7 commit 561087d

8 files changed

Lines changed: 198 additions & 51 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,33 +4,73 @@ on:
44
push:
55
branches:
66
- dev
7-
- prod
7+
workflow_dispatch:
8+
inputs:
9+
environment:
10+
description: "Environment to deploy to"
11+
required: true
12+
type: choice
13+
options:
14+
- dev
15+
- prod
16+
default: prod
17+
ref:
18+
description: "Optional git ref (commit SHA, branch, or tag) to deploy (for rollback)"
19+
required: false
20+
default: ""
21+
22+
permissions:
23+
id-token: write
24+
contents: write # needed for tagging and release creation
25+
actions: read
826

927
jobs:
1028
cdk-deploy:
1129
runs-on: ubuntu-latest
12-
# These permissions are needed to interact with GitHub's OIDC Token endpoint.
13-
permissions:
14-
id-token: write
15-
contents: read
1630

1731
steps:
18-
- name: Set deployment account and role
32+
# ----------------------------------------------------
33+
# 🧭 Determine environment + AWS role + tagging behavior
34+
# ----------------------------------------------------
35+
- name: Determine deployment target
1936
id: set_account
2037
run: |
21-
if [[ "${GITHUB_REF##*/}" == "dev" ]]; then
22-
echo "account_name=dev" >> $GITHUB_ENV
23-
echo "role_arn=arn:aws:iam::449431850278:role/GitHubDeploy" >> $GITHUB_ENV
24-
elif [[ "${GITHUB_REF##*/}" == "prod" ]]; then
25-
echo "account_name=prod" >> $GITHUB_ENV
26-
echo "role_arn=arn:aws:iam::593025701104:role/GitHubDeploy" >> $GITHUB_ENV
38+
if [[ "${GITHUB_EVENT_NAME}" == "push" ]]; then
39+
if [[ "${GITHUB_REF##*/}" == "dev" ]]; then
40+
echo "account_name=dev" >> $GITHUB_ENV
41+
echo "role_arn=arn:aws:iam::449431850278:role/GitHubDeploy" >> $GITHUB_ENV
42+
echo "should_tag=false" >> $GITHUB_ENV
43+
else
44+
echo "Branch not configured for deployment." && exit 1
45+
fi
46+
elif [[ "${GITHUB_EVENT_NAME}" == "workflow_dispatch" ]]; then
47+
if [[ "${{ github.event.inputs.environment }}" == "dev" ]]; then
48+
echo "account_name=dev" >> $GITHUB_ENV
49+
echo "role_arn=arn:aws:iam::449431850278:role/GitHubDeploy" >> $GITHUB_ENV
50+
echo "should_tag=false" >> $GITHUB_ENV
51+
elif [[ "${{ github.event.inputs.environment }}" == "prod" ]]; then
52+
echo "account_name=prod" >> $GITHUB_ENV
53+
echo "role_arn=arn:aws:iam::593025701104:role/GitHubDeploy" >> $GITHUB_ENV
54+
echo "should_tag=true" >> $GITHUB_ENV
55+
else
56+
echo "Invalid environment specified." && exit 1
57+
fi
2758
else
28-
echo "Branch not configured for deployment." && exit 1
59+
echo "Unsupported trigger type" && exit 1
2960
fi
61+
62+
# ----------------------------------------------------
63+
# 🔄 Checkout code (use ref input if provided for rollback)
64+
# ----------------------------------------------------
3065
- uses: actions/checkout@v4
66+
with:
67+
fetch-depth: 0
68+
ref: ${{ github.event.inputs.ref || github.ref }}
69+
3170
- uses: actions/setup-python@v5
3271
with:
3372
python-version: "3.11"
73+
3474
- uses: Gr1N/setup-poetry@v8
3575
with:
3676
poetry-version: "1.8.0"
@@ -50,16 +90,33 @@ jobs:
5090
role-to-assume: ${{ env.role_arn }}
5191
aws-region: us-west-2
5292

93+
# ----------------------------------------------------
94+
# 🧱 CDK Synth + Deploy
95+
# ----------------------------------------------------
5396
- name: Synth
5497
env:
5598
ACCOUNT_NAME: ${{ env.account_name }}
5699
run: |
100+
echo "Synthesizing for environment: $ACCOUNT_NAME"
57101
# poetry run to get the environment we installed everything into
58102
poetry run cdk synth --context account_name=$ACCOUNT_NAME
59103
60104
- name: Deploy
61105
env:
62106
ACCOUNT_NAME: ${{ env.account_name }}
63107
run: |
108+
echo "Deploying to environment: $ACCOUNT_NAME"
64109
# poetry run to get the environment we installed everything into
65110
poetry run cdk deploy --all --context account_name=$ACCOUNT_NAME --require-approval never
111+
112+
# ----------------------------------------------------
113+
# 🏷️ Tag Release (prod only)
114+
# ----------------------------------------------------
115+
- name: Create tag
116+
if: env.should_tag == 'true'
117+
run: |
118+
TAG_NAME="prod-$(date -u +'%Y-%m-%d-%H%M%S')"
119+
echo "TAG_NAME=$TAG_NAME" >> $GITHUB_ENV
120+
git tag -a "$TAG_NAME" -m "Production deployment on $(date -u)"
121+
git push origin "$TAG_NAME"
122+
echo "Created tag $TAG_NAME"

lambda_layer/database/requirements.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -153,9 +153,9 @@ greenlet==3.2.2 ; python_version < "3.14" and (platform_machine == "aarch64" or
153153
idna==3.10 ; python_version >= "3.10" and python_version < "4" \
154154
--hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
155155
--hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
156-
imap-data-access==0.36.0 ; python_version >= "3.10" and python_version < "4" \
157-
--hash=sha256:e221c55395bc3a1163432110b67ec544566f87e1e332bd3da2c9f833c765136c \
158-
--hash=sha256:edf8a57c89759bcf40979b290e5fa368f71b34094d757c203d1086ad57818a79
156+
imap-data-access==0.37.0 ; python_version >= "3.10" and python_version < "4" \
157+
--hash=sha256:7887ad43c4404c6465035af73621237aef7a8d88d506439dd4618aef1db8cf87 \
158+
--hash=sha256:9801aba311311815866336636fdad9e37b530498f4c3f21abce283d860a7c643
159159
psycopg2-binary==2.9.10 ; python_version >= "3.10" and python_version < "4" \
160160
--hash=sha256:04392983d0bb89a8717772a193cfaac58871321e3ec69514e1c4e0d4957b5aff \
161161
--hash=sha256:056470c3dc57904bbf63d6f534988bafc4e970ffd50f6271fc4ee7daad9498a5 \

lambda_layer/spice/requirements.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,9 @@ charset-normalizer==3.4.2 ; python_version >= "3.10" and python_version < "4" \
9797
idna==3.10 ; python_version >= "3.10" and python_version < "4" \
9898
--hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
9999
--hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
100-
imap-data-access==0.36.0 ; python_version >= "3.10" and python_version < "4" \
101-
--hash=sha256:e221c55395bc3a1163432110b67ec544566f87e1e332bd3da2c9f833c765136c \
102-
--hash=sha256:edf8a57c89759bcf40979b290e5fa368f71b34094d757c203d1086ad57818a79
100+
imap-data-access==0.37.0 ; python_version >= "3.10" and python_version < "4" \
101+
--hash=sha256:7887ad43c4404c6465035af73621237aef7a8d88d506439dd4618aef1db8cf87 \
102+
--hash=sha256:9801aba311311815866336636fdad9e37b530498f4c3f21abce283d860a7c643
103103
numpy==2.2.6 ; python_version >= "3.10" and python_version < "4" \
104104
--hash=sha256:038613e9fb8c72b0a41f025a7e4c3f0b7a1b5d768ece4796b674c8f3fe13efff \
105105
--hash=sha256:0678000bb9ac1475cd454c6b8c799206af8107e310843532b04d49649c717a47 \

poetry.lock

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ python = ">=3.10,<4"
3232
# WARNING - Please run this command when updateing `imap-data-access` to ensure that
3333
# the correct version and hash are used:
3434
# poetry export -f requirements.txt -o lambda_layer/database/requirements.txt --with layer-database
35-
imap-data-access = ">=0.36.0"
35+
imap-data-access = ">=0.37.0"
3636

3737
# Optional dependencies - install with `poetry install -E docs`
3838
sphinx = {version="^7.1.0", optional=true}

sds_data_manager/lambda_code/SDSCode/pipeline_lambdas/batch_starter.py

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -180,43 +180,63 @@ def filter_conditions(table):
180180
)
181181
return conditions
182182

183-
# First check to see if there are any jobs in progress and get the max version
183+
# Step 1: query to get the max version from the processing jobs table
184184
max_version_record = (
185185
session.query(models.ProcessingJob)
186186
.filter(*filter_conditions(models.ProcessingJob))
187187
.order_by(models.ProcessingJob.version.desc())
188188
.first()
189189
)
190190
if max_version_record:
191-
max_version = max_version_record.version
192-
# If there is a job already in progress, determine whether the current job
193-
# is a duplicate of the in-progress job by checking the dependency file hash.
194-
# If the hashes are different, then we know the dependencies have changed and
195-
# we should bump the version number and continue with processing.
191+
max_version_processing = max_version_record.version
192+
# Step 2: If there is a job already in progress, determine whether the current
193+
# job is a duplicate of the in-progress job by checking the dependency file
194+
# hash. If the hashes are different, then we know the dependencies have changed
195+
# and we should bump the version number and continue with processing.
196196
if max_version_record.status == models.Status.INPROGRESS:
197197
command = max_version_record.container_command
198198
if dependency_hash(current_dependencies) in command:
199199
# Return the current max version and this job will not proceed if
200200
# everything else is the same.
201-
return max_version
202-
logger.info(
203-
f"Job with id: {max_version_record.id} is in progress, but the "
204-
f"dependencies have changed. Bumping version number."
205-
)
201+
return max_version_processing
202+
else:
203+
# Dependencies have changed, so bump the version number.
204+
logger.info(
205+
f"Job with id: {max_version_record.id} is in progress, but the "
206+
f"dependencies have changed. Bumping version number."
207+
)
208+
return f"v{int(max_version_processing[1:]) + 1:03d}"
209+
206210
else:
207-
max_version = None
208-
# If the descriptor is "all", we should only check the processing job table. The
209-
# ScienceFiles table does not have descriptors of "all" since the products
210-
# produced will have their own specific descriptors.
211-
if descriptor == "all":
212-
return f"v{int(max_version[1:]) + 1:03d}" if max_version else "v001"
213-
# If no jobs are in progress, check the science files table for the max version.
214-
if not max_version:
215-
max_version = (
216-
session.query(func.max(models.ScienceFiles.version)).filter(
217-
*filter_conditions(models.ScienceFiles)
218-
)
219-
).scalar()
211+
max_version_processing = None
212+
# Step 3: If the descriptor is "all", only use the max version from the processing
213+
# job table. The ScienceFiles table does not have descriptors of "all" since the
214+
# products produced will have their own specific descriptors.
215+
if "all" in descriptor:
216+
return (
217+
f"v{int(max_version_processing[1:]) + 1:03d}"
218+
if max_version_processing
219+
else "v001"
220+
)
221+
222+
# Step 4: Get the max version from the science files table.
223+
max_version_sci = (
224+
session.query(func.max(models.ScienceFiles.version)).filter(
225+
*filter_conditions(models.ScienceFiles)
226+
)
227+
).scalar()
228+
229+
# Step 5: By default, use the max version from the science files table unless
230+
# it is a spacecraft "pointing-attitude" job. If a so, then use the max version
231+
# from the processing jobs table. If the job is a spacecraft pointing-attitude job,
232+
# it will produce a SPICE kernel and not a science file. There is no way to
233+
# determine the filename of the kernel that will be produced, so we rely on the max
234+
# version from the processing jobs table.
235+
if instrument == "spacecraft" and descriptor == "pointing-attitude":
236+
max_version = max_version_processing
237+
else:
238+
max_version = max_version_sci
239+
220240
# Bump the version number. "V001" will be returned if max_version is None.
221241
return f"v{int(max_version[1:]) + 1:03d}" if max_version else "v001"
222242

sds_data_manager/lambda_code/processing/requirements.txt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,9 @@ charset-normalizer==3.4.2 ; python_version >= "3.10" and python_version < "4" \
142142
idna==3.10 ; python_version >= "3.10" and python_version < "4" \
143143
--hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \
144144
--hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3
145-
imap-data-access==0.36.0 ; python_version >= "3.10" and python_version < "4" \
146-
--hash=sha256:e221c55395bc3a1163432110b67ec544566f87e1e332bd3da2c9f833c765136c \
147-
--hash=sha256:edf8a57c89759bcf40979b290e5fa368f71b34094d757c203d1086ad57818a79
145+
imap-data-access==0.37.0 ; python_version >= "3.10" and python_version < "4" \
146+
--hash=sha256:7887ad43c4404c6465035af73621237aef7a8d88d506439dd4618aef1db8cf87 \
147+
--hash=sha256:9801aba311311815866336636fdad9e37b530498f4c3f21abce283d860a7c643
148148
imap-processing==1.0.0 ; python_version >= "3.10" and python_version < "4" \
149149
--hash=sha256:808c614dbd4d1a198972bd224416bcb16a933b12bfe0a5391cac21ea198aca32 \
150150
--hash=sha256:f71001020a0047f9ceba9a2803384e34f669821779f88619e14c2cd598fa75fc

tests/lambda_endpoints/test_batch_starter.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2110,3 +2110,73 @@ def test_lambda_skip_processing_due_to_crid_check(session, caplog):
21102110
# Verify the job was skipped
21112111
assert log in caplog.text
21122112
assert mock_submit.call_count == 0
2113+
2114+
2115+
# Add tests to verify that the correct version is calculated.
2116+
def test_determine_job_version_science(session):
2117+
"""Tests ``determine_job_version`` for science jobs."""
2118+
# For science files, the job version should be determined from the science files
2119+
# table. Although there is a successful job with v003, the latest science file is
2120+
# v001, so the next version should be v002. It is possible for a job to have
2121+
# Status = SUCCEEDED, but no files were produced for the job, which is why we check
2122+
# the science files table for the version.
2123+
records = [
2124+
ScienceFiles(
2125+
file_path="/path/to/imap_lo_l1a_de_20240101_v002.cdf",
2126+
instrument="lo",
2127+
data_level="l1a",
2128+
descriptor="de",
2129+
start_date=datetime(2024, 1, 1),
2130+
version="v001",
2131+
extension="cdf",
2132+
ingestion_date=datetime.strptime(
2133+
"2024-01-25 23:35:26+00:00", "%Y-%m-%d %H:%M:%S%z"
2134+
),
2135+
),
2136+
ProcessingJob(
2137+
status=models.Status.SUCCEEDED,
2138+
instrument="lo",
2139+
data_level="l1a",
2140+
descriptor="de",
2141+
start_date=datetime(2024, 1, 1),
2142+
version="v003",
2143+
),
2144+
]
2145+
session.add_all(records)
2146+
session.add_all(records)
2147+
version = determine_job_version(
2148+
session, "lo", "l1a", "de", datetime(2024, 1, 1), "test_dependency"
2149+
)
2150+
# The version should be v002
2151+
assert version == "v002"
2152+
2153+
2154+
def test_determine_job_version_spacecraft(session):
2155+
"""Tests ``determine_job_version`` for spacecraft jobs."""
2156+
# the function determine_job_version uses the processing job table to determine
2157+
# the correct version for a spacecraft pointing-attitude job, since there is no way
2158+
# to determine the filename and therefore the version from the spice table using the
2159+
# information given. Assert that the version is calculated from the processing
2160+
# job table.
2161+
records = [
2162+
# Add a processing job with version 1
2163+
ProcessingJob(
2164+
status=models.Status.SUCCEEDED,
2165+
instrument="spacecraft",
2166+
data_level="l1a",
2167+
descriptor="pointing-attitude",
2168+
start_date=datetime(2024, 1, 1),
2169+
version="v002",
2170+
)
2171+
]
2172+
session.add_all(records)
2173+
version = determine_job_version(
2174+
session,
2175+
"spacecraft",
2176+
"l1a",
2177+
"pointing-attitude",
2178+
datetime(2024, 1, 1),
2179+
"test_dependency",
2180+
)
2181+
# The version should be v003 since there was a successful job with v002
2182+
assert version == "v003"

0 commit comments

Comments
 (0)