Skip to content

Commit 8ed7870

Browse files
committed
feat: updates for 2025-11-01
1 parent adb7820 commit 8ed7870

File tree

15 files changed

+942
-62
lines changed

15 files changed

+942
-62
lines changed

.github/dependabot.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: "npm"
4+
directory: "/"
5+
schedule:
6+
interval: "weekly"
7+
open-pull-requests-limit: 2
8+
versioning-strategy: "auto"
9+
groups:
10+
all-dependencies:
11+
patterns:
12+
- "*"
13+
commit-message:
14+
prefix: "chore"
15+
prefix-development: "chore"
16+
include: "scope"
17+
18+
- package-ecosystem: "pip"
19+
directory: "/"
20+
schedule:
21+
interval: "weekly"
22+
open-pull-requests-limit: 2
23+
versioning-strategy: "auto"
24+
groups:
25+
all-dependencies:
26+
patterns:
27+
- "*"
28+
commit-message:
29+
prefix: "chore"
30+
prefix-development: "chore"
31+
include: "scope"
32+
33+
- package-ecosystem: "github-actions"
34+
directory: "/"
35+
schedule:
36+
interval: "weekly"
37+
open-pull-requests-limit: 5
38+

.github/workflows/ci.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v5
16+
17+
- name: Set up Node.js
18+
uses: actions/setup-node@v6
19+
with:
20+
node-version: '22'
21+
22+
- name: Install uv
23+
uses: astral-sh/setup-uv@v7
24+
25+
- name: Install Python dependencies
26+
run: uv sync
27+
28+
- name: Install Node dependencies
29+
run: npm install
30+
31+
- name: Run pre-commit
32+
run: uv run pre-commit run --all-files
33+
34+
- name: Set dummy AWS credentials
35+
run: |
36+
- name: Synthesize CDK stack
37+
env:
38+
AWS_ACCESS_KEY_ID: AKIAIOSFODNN7EXAMPLE
39+
AWS_SECRET_ACCESS_KEY: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
40+
AWS_REGION: us-east-1
41+
AWS_DEFAULT_REGION: us-east-1
42+
DATA_ACCESS_ROLE_ARN: arn:aws:iam::123456789012:role/DummyDataAccessRole
43+
44+
45+
run: uv run npx cdk synth --all

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,4 @@ node_modules/
168168
.pgdata
169169

170170
.ruff_cache/
171+
.envrc

.pre-commit-config.yaml

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
repos:
2-
- repo: https://github.com/PyCQA/isort
3-
rev: 5.13.2
2+
- repo: https://github.com/tsvikas/sync-with-uv
3+
rev: v0.4.0
44
hooks:
5-
- id: isort
6-
language_version: python
7-
args: ["-m", "3","--trailing-comma", "-l", "88"]
8-
5+
- id: sync-with-uv
96
- repo: https://github.com/astral-sh/ruff-pre-commit
10-
rev: v0.4.4
7+
rev: v0.14.3
118
hooks:
129
- id: ruff
1310
args: ["--fix"]
1411
- id: ruff-format
1512

1613
- repo: https://github.com/pre-commit/mirrors-mypy
17-
rev: v1.10.0
14+
rev: v1.18.2
1815
hooks:
1916
- id: mypy
2017
language_version: python

.python-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.12

README.md

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,59 +6,81 @@ Template repository to deploy [eoapi](https://eoapi.dev) on AWS using the [eoapi
66

77
- python >=3.9
88
- docker
9-
- node >=14
9+
- node >=18
1010
- AWS credentials environment variables configured to point to an account.
1111
- **Optional** a `config.yaml` file to override the default deployment settings defined in `config.py`.
1212

1313
## Installation
1414

15-
Install python dependencies with
15+
Install python dependencies with `uv`
1616

17-
```
18-
python -m venv .venv
19-
source .venv/bin/activate
20-
python -m pip install -r requirements.txt
17+
```bash
18+
uv sync
2119
```
2220

2321
And node dependencies with
2422

25-
```
23+
```bash
2624
npm install
2725
```
2826

2927
Verify that the `cdk` CLI is available. Since `aws-cdk` is installed as a local dependency, you can use the `npx` node package runner tool, that comes with `npm`.
3028

31-
```
29+
```bash
3230
npx cdk --version
3331
```
32+
3433
## Deployment
3534

36-
First, synthesize the app
35+
### Configuration
3736

37+
You can configure your eoAPI deployment using either environment variables (defined manually or in a `.env` file) or a configuration yaml file (see [config.py](./infrastructure/config.py) for more details on all of the configurable parameters.
38+
39+
Feel free to add or subtract from these configuration parameters to suit your needs!
40+
41+
To start you can copy [config.yaml.example](./config.yaml.example) to config.yaml:
42+
43+
```bash
44+
cp config.yaml.example config.yaml
3845
```
39-
npx cdk synth --all
46+
47+
Then update the values according to your preferences.
48+
Be sure to set `project_id` to something recognizable and to look closely at all of the components that you are including with each setting.
49+
50+
### AWS credentials
51+
52+
For the deployment steps to work, you will need to have your environment configured with your AWS account credentials.
53+
There are lots of ways to do this so choose whatever method you want to define `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_REGION`, dtc.
54+
55+
### Synthesize the CDK Stack
56+
57+
You can test your deployment configuration without deploying any actual resources to AWS by using the `cdk synth` command.
58+
59+
```bash
60+
uv run npx cdk synth --all
4061
```
4162

4263
Then, deploy
4364

44-
```
45-
npx cdk deploy --all --require-approval never
65+
```bash
66+
uv run npx cdk deploy --all --require-approval never
4667
```
4768

4869
## Docker
4970

5071
Before deploying the application on the cloud, you can start by exploring it with a local *Docker* deployment
5172

52-
```
73+
```bash
5374
docker compose up
5475
```
5576

5677
Once the applications are *up*, you'll need to add STAC **Collections** and **Items** to the PgSTAC database. If you don't have, you can use the follow the [MAXAR open data demo](https://github.com/vincentsarago/MAXAR_opendata_to_pgstac) (or get inspired by the other [demos](https://github.com/developmentseed/eoAPI/tree/main/demo)).
5778

5879
Then you can start exploring your dataset with:
5980

60-
- the STAC Metadata service [http://localhost:8081](http://localhost:8081)
61-
- the Raster service [http://localhost:8082](http://localhost:8082)
62-
- the browser UI [http://localhost:8085](http://localhost:8085)
81+
- the STAC Metadata service [http://localhost:8081](http://localhost:8081)
82+
- the Raster service [http://localhost:8082](http://localhost:8082)
83+
- the Vector service [http://localhost:8083](http://localhost:8083)
84+
- the browser UI [http://localhost:8085](http://localhost:8085)
6385

6486
If you've added a vector dataset to the `public` schema in the Postgres database, they will be available through the **Vector** service at [http://localhost:8083](http://localhost:8083).

config.yaml.example

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
project_id: "eoapi-yo"
2-
stage: "production"
1+
project_id: "eoapi"
2+
stage: "test"
33
tags: {owner: user_a}
44

55
# Ingest Options
@@ -12,7 +12,7 @@ db_allocated_storage: 5
1212
public_db_subnet: False
1313

1414
# VPC Options
15-
nat_gateway_count: 4
15+
nat_gateway_count: 0
1616

1717
# Bastion Host Options
1818
bastion_host: True

docker-compose.yml

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,8 @@ services:
1414
- database
1515

1616
stac:
17-
# Note:
18-
# the official ghcr.io/stac-utils/stac-fastapi-pgstac image uses python 3.8 and uvicorn
19-
# which is why here we use a custom Dockerfile using python 3.11 and gunicorn
20-
build:
21-
context: .
22-
dockerfile: dockerfiles/Dockerfile.stac
17+
platform: linux/amd64
18+
image: ghcr.io/stac-utils/stac-fastapi-pgstac:6.0.2
2319
ports:
2420
- "${MY_DOCKER_IP:-127.0.0.1}:8081:8081"
2521
environment:
@@ -46,7 +42,7 @@ services:
4642
- DB_MAX_CONN_SIZE=10
4743
depends_on:
4844
- database
49-
command: bash -c "bash /tmp/scripts/wait-for-it.sh -t 120 -h database -p 5432 && /start.sh"
45+
command: bash -c "bash /tmp/scripts/wait-for-it.sh -t 120 -h database -p 5432 && uvicorn stac_fastapi.pgstac.app:app --host 0.0.0.0 --port 8081 --workers 1"
5046
volumes:
5147
- ./dockerfiles/scripts:/tmp/scripts
5248

@@ -95,12 +91,12 @@ services:
9591
- AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
9692
depends_on:
9793
- database
98-
command: bash -c "bash /tmp/scripts/wait-for-it.sh -t 120 -h database -p 5432 && gunicorn -k uvicorn.workers.UvicornWorker titiler.pgstac.main:app --bind 0.0.0.0:8082 --workers 1"
94+
command: bash -c "bash /tmp/scripts/wait-for-it.sh -t 120 -h database -p 5432 && uvicorn titiler.pgstac.main:app --host 0.0.0.0 --port 8082 --workers 5"
9995
volumes:
10096
- ./dockerfiles/scripts:/tmp/scripts
10197

10298
vector:
103-
image: ghcr.io/developmentseed/tipg:0.6.3
99+
image: ghcr.io/developmentseed/tipg:1.2.1
104100
ports:
105101
- "${MY_DOCKER_IP:-127.0.0.1}:8083:8083"
106102
environment:
@@ -121,14 +117,15 @@ services:
121117
- POSTGRES_PORT=5432
122118
- DB_MIN_CONN_SIZE=1
123119
- DB_MAX_CONN_SIZE=10
124-
command: bash -c "bash /tmp/scripts/wait-for-it.sh -t 120 -h database -p 5432 && /start.sh"
120+
command:
121+
bash -c "bash /tmp/scripts/wait-for-it.sh database:5432 --timeout=30 && uvicorn tipg.main:app --host 0.0.0.0 --port 8081 --workers 5"
125122
depends_on:
126123
- database
127124
volumes:
128125
- ./dockerfiles/scripts:/tmp/scripts
129126

130127
database:
131-
image: ghcr.io/stac-utils/pgstac:v0.8.5
128+
image: ghcr.io/stac-utils/pgstac:v0.9.8
132129
environment:
133130
- POSTGRES_USER=username
134131
- POSTGRES_PASSWORD=password

dockerfiles/Dockerfile.stac

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

infrastructure/app.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
aws_s3,
1212
)
1313
from aws_cdk.aws_apigateway import DomainNameOptions
14-
from aws_cdk.aws_apigatewayv2_alpha import DomainName
14+
from aws_cdk.aws_apigatewayv2 import DomainName
1515
from config import AppConfig
1616
from constructs import Construct
1717
from eoapi_cdk import (
@@ -102,7 +102,7 @@ def __init__(
102102
add_pgbouncer=True,
103103
vpc=vpc,
104104
engine=aws_rds.DatabaseInstanceEngine.postgres(
105-
version=aws_rds.PostgresEngineVersion.VER_16
105+
version=aws_rds.PostgresEngineVersion.VER_17
106106
),
107107
vpc_subnets=aws_ec2.SubnetSelection(
108108
subnet_type=(
@@ -130,6 +130,9 @@ def __init__(
130130
"NAME": app_config.build_service_name("stac"),
131131
"description": f"{app_config.stage} STAC API",
132132
},
133+
# SnapStart: https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html
134+
# enable this to reduce API cold start times (comes with a fixed cost increase)
135+
enable_snap_start=False,
133136
db=pgstac_db.connection_target,
134137
db_secret=pgstac_db.pgstac_secret,
135138
# If the db is not in the public subnet then we need to put
@@ -165,6 +168,9 @@ def __init__(
165168
"NAME": app_config.build_service_name("raster"),
166169
"description": f"{app_config.stage} Raster API",
167170
},
171+
# SnapStart: https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html
172+
# enable this to reduce API cold start times (comes with a fixed cost increase)
173+
enable_snap_start=False,
168174
db=pgstac_db.connection_target,
169175
db_secret=pgstac_db.pgstac_secret,
170176
# If the db is not in the public subnet then we need to put
@@ -203,6 +209,9 @@ def __init__(
203209
"NAME": app_config.build_service_name("vector"),
204210
"description": f"{app_config.stage} tipg API",
205211
},
212+
# SnapStart: https://docs.aws.amazon.com/lambda/latest/dg/snapstart.html
213+
# enable this to reduce API cold start times (comes with a fixed cost increase)
214+
enable_snap_start=False,
206215
# If the db is not in the public subnet then we need to put
207216
# the lambda within the VPC
208217
vpc=vpc if not app_config.public_db_subnet else None,
@@ -355,14 +364,17 @@ def _grant_assume_role_with_principal_pattern(
355364
self,
356365
role_to_assume: aws_iam.Role,
357366
principal_pattern: str,
358-
account_id: str = boto3.client("sts").get_caller_identity().get("Account"),
367+
account_id: str | None = None,
359368
) -> aws_iam.Role:
360369
"""
361370
Grants assume role permissions to the role of the given
362371
account with the given name pattern. Default account
363372
is the current account.
364373
"""
365374

375+
if not account_id:
376+
account_id = boto3.client("sts").get_caller_identity().get("Account")
377+
366378
role_to_assume.assume_role_policy.add_statements(
367379
aws_iam.PolicyStatement(
368380
effect=aws_iam.Effect.ALLOW,

0 commit comments

Comments
 (0)