Skip to content

Commit caf53cc

Browse files
committed
Add CI/CD
1 parent ecd6e1e commit caf53cc

3 files changed

Lines changed: 157 additions & 0 deletions

File tree

.github/workflows/deploy.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Deploy to EC2
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
8+
jobs:
9+
deploy:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Checkout repository
14+
uses: actions/checkout@v4
15+
16+
- name: Create deployment bundle
17+
run: |
18+
set -euo pipefail
19+
tar czf nasa-skyview.tar.gz requirements.txt src web deploy
20+
21+
- name: Upload application bundle
22+
uses: appleboy/scp-action@v0.1.7
23+
with:
24+
host: ${{ secrets.EC2_HOST }}
25+
username: ${{ secrets.EC2_USER }}
26+
key: ${{ secrets.EC2_SSH_KEY }}
27+
source: "nasa-skyview.tar.gz"
28+
target: "/tmp/nasa-skyview"
29+
30+
- name: Deploy to EC2
31+
uses: appleboy/ssh-action@v1.0.3
32+
with:
33+
host: ${{ secrets.EC2_HOST }}
34+
username: ${{ secrets.EC2_USER }}
35+
key: ${{ secrets.EC2_SSH_KEY }}
36+
script: |
37+
set -euo pipefail
38+
ARCHIVE="/tmp/nasa-skyview/nasa-skyview.tar.gz"
39+
APP_SRC="/tmp/nasa-skyview/app"
40+
INSTALL_DIR="${{ secrets.EC2_INSTALL_DIR || '/opt/nasa-skyview' }}"
41+
PYTHON_BIN="${{ secrets.EC2_PYTHON_BIN || 'python3' }}"
42+
rm -rf "$APP_SRC"
43+
mkdir -p "$APP_SRC"
44+
tar xzf "$ARCHIVE" -C "$APP_SRC"
45+
chmod +x "$APP_SRC/deploy/deploy.sh"
46+
"$APP_SRC/deploy/deploy.sh" "$APP_SRC" "$INSTALL_DIR" "$PYTHON_BIN"
47+
rm -rf "$APP_SRC" "$ARCHIVE"

README.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,59 @@ Then open <http://127.0.0.1:8000/app> in your browser. Rotate the sphere with yo
6565
### 4. Inspect available surveys
6666

6767
NASA maintains the full survey catalogue at <https://skyview.gsfc.nasa.gov/current/cgi/survey.pl>. Any entry in the "Survey" column is compatible with the `--survey` option.
68+
69+
## ☁️ Continuous deployment on AWS EC2 (native runtime)
70+
71+
Every push to `main` now syncs the repository to an EC2 instance and restarts a systemd-managed uvicorn process—no containers required.
72+
73+
### 1. Prepare the EC2 host (one-time)
74+
75+
1. Launch an EC2 instance (Ubuntu 22.04+ or Amazon Linux 2023) with inbound access to TCP 8000 (or front it with an ALB/NGINX if you prefer port 80/443).
76+
2. Install system packages:
77+
78+
```bash
79+
sudo apt update && sudo apt install -y python3 python3-venv python3-pip git
80+
# Amazon Linux: sudo dnf install -y python3 python3-venv git
81+
```
82+
83+
3. Create a deployment directory and give your SSH user ownership:
84+
85+
```bash
86+
sudo mkdir -p /opt/nasa-skyview/outputs
87+
sudo chown $USER:$USER /opt/nasa-skyview/outputs
88+
```
89+
90+
4. Ensure outbound internet access so the instance can reach NASA SkyView and PyPI.
91+
92+
### 2. Configure GitHub secrets
93+
94+
Populate these secrets so `.github/workflows/deploy.yml` can transfer the code and execute the deployment script:
95+
96+
| Secret | Description |
97+
| --- | --- |
98+
| `EC2_HOST` | Public DNS name or IP of the EC2 instance. |
99+
| `EC2_USER` | SSH username (`ubuntu`, `ec2-user`, etc.). |
100+
| `EC2_SSH_KEY` | Private SSH key (PEM contents) matching the instance key pair. |
101+
| `EC2_INSTALL_DIR` *(optional)* | Alternate install path (defaults to `/opt/nasa-skyview`). |
102+
| `EC2_PYTHON_BIN` *(optional)* | Explicit Python interpreter (`python3.11`, etc.). |
103+
104+
> AWS credentials are no longer required because the workflow connects directly over SSH.
105+
106+
### 3. How the pipeline deploys
107+
108+
1. GitHub Actions bundles `requirements.txt`, `src/`, `web/`, and `deploy/` into a tarball.
109+
2. The tarball is uploaded to `/tmp/nasa-skyview/` on the EC2 host.
110+
3. The remote script runs `deploy/deploy.sh`, which:
111+
- Copies the code into `/opt/nasa-skyview/app`.
112+
- Creates/updates a Python virtual environment in `/opt/nasa-skyview/venv`.
113+
- Installs Python dependencies with `pip`.
114+
- Installs/updates the systemd unit file `deploy/nasa-skyview.service`.
115+
- Restarts the `nasa-skyview` service (serving on port 8000 by default).
116+
117+
Logs are written to `/var/log/nasa-skyview.log` and `/var/log/nasa-skyview.err`, and cached SkyView tiles persist in `/opt/nasa-skyview/outputs`.
118+
119+
To roll back, re-run the workflow on an earlier commit or SSH into the instance, check out the desired commit manually inside `/opt/nasa-skyview/app`, reinstall requirements, and restart the service (`sudo systemctl restart nasa-skyview`).
120+
121+
## 🛣️ Roadmap ideas
122+
123+
- Package the downloader as a service with caching and rate-limit protection.

deploy/deploy.sh

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
if [[ $# -lt 2 ]]; then
5+
echo "Usage: $0 <source-dir> <install-dir> [python-bin]" >&2
6+
exit 1
7+
fi
8+
9+
SOURCE_DIR="$1"
10+
INSTALL_DIR="$2"
11+
PYTHON_BIN="${3:-python3}"
12+
13+
APP_DIR="$INSTALL_DIR/app"
14+
VENV_DIR="$INSTALL_DIR/venv"
15+
OUTPUT_DIR="$APP_DIR/outputs"
16+
LOG_DIR="/var/log"
17+
SERVICE_FILE="/etc/systemd/system/nasa-skyview.service"
18+
19+
if [[ ! -d "$SOURCE_DIR" ]]; then
20+
echo "Source directory '$SOURCE_DIR' does not exist" >&2
21+
exit 1
22+
fi
23+
24+
sudo mkdir -p "$INSTALL_DIR"
25+
sudo chown -R "$USER":"$USER" "$INSTALL_DIR"
26+
27+
mkdir -p "$APP_DIR"
28+
rm -rf "$APP_DIR/src" "$APP_DIR/web"
29+
cp -r "$SOURCE_DIR/src" "$APP_DIR/"
30+
cp -r "$SOURCE_DIR/web" "$APP_DIR/"
31+
cp "$SOURCE_DIR/requirements.txt" "$APP_DIR/requirements.txt"
32+
33+
if [[ ! -d "$VENV_DIR" ]]; then
34+
"$PYTHON_BIN" -m venv "$VENV_DIR"
35+
fi
36+
37+
"$VENV_DIR/bin/pip" install --upgrade pip
38+
"$VENV_DIR/bin/pip" install -r "$APP_DIR/requirements.txt"
39+
40+
mkdir -p "$OUTPUT_DIR"
41+
42+
sudo touch "$LOG_DIR/nasa-skyview.log" "$LOG_DIR/nasa-skyview.err"
43+
sudo chown "$USER":"$USER" "$LOG_DIR/nasa-skyview.log" "$LOG_DIR/nasa-skyview.err"
44+
45+
sudo cp "$SOURCE_DIR/deploy/nasa-skyview.service" "$SERVICE_FILE"
46+
sudo sed -i "s|@@APP_DIR@@|$APP_DIR|g" "$SERVICE_FILE"
47+
sudo sed -i "s|@@VENV_DIR@@|$VENV_DIR|g" "$SERVICE_FILE"
48+
49+
sudo systemctl daemon-reload
50+
sudo systemctl enable nasa-skyview.service
51+
sudo systemctl restart nasa-skyview.service || sudo systemctl start nasa-skyview.service
52+
53+
echo "Deployment complete. Service status:"
54+
sudo systemctl --no-pager status nasa-skyview.service

0 commit comments

Comments
 (0)