Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
version: 2
updates:
- package-ecosystem: "docker"
directory: "/deploy"
schedule:
interval: "weekly"
cooldown:
default-days: 5
- package-ecosystem: "uv"
directory: "/"
schedule:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:

# Keep deploy-staging.yaml and these steps in sync
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Install uv
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
Expand Down Expand Up @@ -70,7 +70,7 @@ jobs:
name: Kubernetes admission
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
- uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v6
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
# If you do not check out your code, Copilot will do this for you.
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Install uv
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
Expand Down
15 changes: 10 additions & 5 deletions .github/workflows/deploy-operational-updates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ on:
types: [completed]
branches: [main]

# Prevent concurrent runs since this is deploying to the K8S cluster. Queued runs
# apply in trigger order, which Code Quality's concurrency group makes equal to commit order.
# Prevent concurrent runs since this is deploying to the K8S cluster.
# Queued main pushes apply in trigger order, which Code Quality's concurrency group
# makes equal to commit order. Other completions use separate groups.
concurrency:
group: "deploy"
group: "deploy-${{ github.event.workflow_run.event }}-${{ github.event.workflow_run.head_repository.id }}-${{ github.event.workflow_run.head_branch }}-${{ github.event.workflow_run.conclusion }}"
cancel-in-progress: false

permissions:
Expand All @@ -25,13 +26,17 @@ env:
jobs:
deploy:
name: Deploy
if: ${{ github.event.workflow_run.conclusion == 'success' }}
if: >-
github.event.workflow_run.conclusion == 'success' &&
github.event.workflow_run.event == 'push' &&
github.event.workflow_run.head_repository.full_name == github.repository &&
github.event.workflow_run.head_branch == 'main'
runs-on: ubuntu-24.04
environment: prod

# Keep deploy-staging.yaml and these steps in sync
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
ref: ${{ github.event.workflow_run.head_sha }}

Expand Down
30 changes: 17 additions & 13 deletions .github/workflows/deploy-staging.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ concurrency:
cancel-in-progress: false

permissions:
id-token: write
contents: read

env:
Expand All @@ -23,7 +22,7 @@ jobs:

# Keep code-quality.yaml and these steps in sync
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Install uv
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
Expand Down Expand Up @@ -59,28 +58,30 @@ jobs:
needs: quality
runs-on: ubuntu-24.04
environment: prod
permissions:
id-token: write
contents: read

# Keep deploy-operational-updates.yaml and these steps in sync
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# Fetch main so deploy-staging can compare versions via git show
fetch-depth: 0

- name: Parse branch name
id: parse
env:
BRANCH: ${{ github.ref_name }}
run: |
BRANCH="${{ github.ref_name }}"
# Branch format: stage/{dataset_id}/v{version}
# Strip "stage/" prefix, then split on "/v"
WITHOUT_PREFIX="${BRANCH#stage/}"
DATASET_ID="${WITHOUT_PREFIX%/v*}"
VERSION="${WITHOUT_PREFIX##*/v}"

if [[ "$DATASET_ID" == "$VERSION" || -z "$DATASET_ID" || -z "$VERSION" ]]; then
# Match the dataset and version components before exporting them.
if [[ ! "$BRANCH" =~ ^stage/([a-z0-9][a-z0-9-]*)/v([a-z0-9][a-z0-9.-]*)$ ]]; then
echo "::error::Could not parse dataset_id and version from branch '${BRANCH}'. Expected format: stage/{dataset_id}/v{version}"
exit 1
fi
DATASET_ID="${BASH_REMATCH[1]}"
VERSION="${BASH_REMATCH[2]}"

echo "dataset_id=${DATASET_ID}" >> "$GITHUB_OUTPUT"
echo "version=${VERSION}" >> "$GITHUB_OUTPUT"
Expand Down Expand Up @@ -132,8 +133,11 @@ jobs:
file: deploy/Dockerfile

- name: Deploy staging
env:
DATASET_ID: ${{ steps.parse.outputs.dataset_id }}
VERSION: ${{ steps.parse.outputs.version }}
run: >
uv run main deploy-staging
${{ steps.parse.outputs.dataset_id }}
${{ steps.parse.outputs.version }}
${{ env.IMAGE_TAG }}
"$DATASET_ID"
"$VERSION"
"$IMAGE_TAG"
46 changes: 23 additions & 23 deletions .github/workflows/manual-backfill.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,29 +94,6 @@ jobs:
runs-on: ubuntu-24.04
environment: prod
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- name: Install uv
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7
with:
enable-cache: true
cache-dependency-glob: uv.lock
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97
with:
python-version-file: .python-version
- name: Install the project
run: uv sync --all-extras --dev --locked
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@e1253824e5c10ff9df46874f81ed3ec929e19cfd
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Install kubectl
uses: azure/setup-kubectl@829323503d1be3d00ca8346e5391ca0b07a9ab0d
with:
version: latest
- name: Update kubeconfig
run: aws eks update-kubeconfig --name ${{ secrets.EKS_CLUSTER_NAME }} --region ${{ secrets.AWS_REGION }}
- name: Require main and wait for its deploy
env:
GH_TOKEN: ${{ github.token }}
Expand Down Expand Up @@ -164,6 +141,29 @@ jobs:

echo "::error::Timed out waiting for the deploy of ${GITHUB_SHA}."
exit 1
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1
- name: Install uv
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7
with:
enable-cache: true
cache-dependency-glob: uv.lock
- name: Set up Python
uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97
with:
python-version-file: .python-version
- name: Install the project
run: uv sync --all-extras --dev --locked
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@e1253824e5c10ff9df46874f81ed3ec929e19cfd
with:
role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }}
aws-region: ${{ secrets.AWS_REGION }}
- name: Install kubectl
uses: azure/setup-kubectl@829323503d1be3d00ca8346e5391ca0b07a9ab0d
with:
version: latest
- name: Update kubeconfig
run: aws eks update-kubeconfig --name ${{ secrets.EKS_CLUSTER_NAME }} --region ${{ secrets.AWS_REGION }}
- name: Start backfill (SEE LOGS)
env:
DYNAMICAL_ENV: prod
Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/manual-create-job-from-cronjob.yml
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,13 @@ jobs:
- name: Update kubeconfig
run: aws eks update-kubeconfig --name ${{ secrets.EKS_CLUSTER_NAME }} --region ${{ secrets.AWS_REGION }}
- name: Submit job (SEE LOGS)
env:
CRONJOB_NAME: ${{ github.event.inputs.cronjob_name }}
USERNAME: ${{ github.actor }}
run: |
#!/bin/bash
set -euo pipefail

CRONJOB_NAME="${{ github.event.inputs.cronjob_name }}"
USERNAME="${{ github.actor }}"
RANDOM_CHARS=$(openssl rand -hex 1)

# Generate job name with length limits
Expand All @@ -130,7 +131,7 @@ jobs:
JOB_NAME="${CRONJOB_TRUNCATED}-${USERNAME_TRUNCATED}-${RANDOM_CHARS}"

echo "Creating job: ${JOB_NAME} from cronjob: ${CRONJOB_NAME}"
kubectl create job --from=cronjob/${CRONJOB_NAME} ${JOB_NAME}
kubectl create job "--from=cronjob/${CRONJOB_NAME}" "${JOB_NAME}"

echo ""
echo "## Job Created Successfully"
Expand Down
13 changes: 8 additions & 5 deletions deploy/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
# syntax=docker/dockerfile:1.9
# syntax=docker/dockerfile:1.9@sha256:fe40cf4e92cd0c467be2cfc30657a680ae2398318afd50b0c80585784c604f28

# This file is lightly modified from the original at https://hynek.me/articles/docker-uv/

FROM ghcr.io/astral-sh/uv:0.12.19@sha256:04d046b13e60d6bcec73cbc5e1cad25d680dea90c8573340950a0ac2d1aef424 AS uv
FROM rclone/rclone:1.75.1@sha256:45401ad7410db1d67ffdb58e19059ad20b0d8e0285a60e38bbec55cc1019c7a5 AS rclone

### Use a separate build container for better reuse.
FROM ubuntu:noble AS build
FROM ubuntu:noble@sha256:008173c23f95b170204355c12626cb5a965d779a7e1283b09e9cffbb1bf33ca3 AS build

SHELL ["sh", "-exc"]

Expand All @@ -26,7 +29,7 @@ apt-get install -qyy \
gcc \
EOT

COPY --from=ghcr.io/astral-sh/uv:latest /uv /usr/local/bin/uv
COPY --from=uv /uv /usr/local/bin/uv

# - Silence uv complaining about not being able to use hard links,
# - tell uv to byte-compile packages for faster application startups,
Expand Down Expand Up @@ -79,7 +82,7 @@ RUN --mount=type=cache,target=/root/.cache \

##########################################################################

FROM ubuntu:noble
FROM ubuntu:noble@sha256:008173c23f95b170204355c12626cb5a965d779a7e1283b09e9cffbb1bf33ca3
SHELL ["sh", "-exc"]

# Optional: add the application virtualenv to search path.
Expand Down Expand Up @@ -108,7 +111,7 @@ EOT
COPY --from=build /etc/apt/sources.list.d/deadsnakes-ubuntu-ppa-noble.sources /etc/apt/sources.list.d/

# Copy rclone from official image (Noble's version is too old for `rclone copyurl --urls` flag)
COPY --from=rclone/rclone:latest /usr/local/bin/rclone /usr/bin/rclone
COPY --from=rclone /usr/local/bin/rclone /usr/bin/rclone

# Note how the runtime dependencies differ from build-time ones.
# Notably, there is no uv either!
Expand Down
2 changes: 2 additions & 0 deletions docs/cluster_setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ We use
* `docker` to package the code and dependencies
* `kubernetes` indexed jobs to run work in parallel

Container image inputs in `deploy/Dockerfile` are pinned to multi-platform digests. Dependabot proposes base and tool image updates weekly, with a five-day cooldown. Update the Dockerfile frontend and Hatchling build-backend pins manually. Verify both AMD64 and ARM64 builds when updating pins; Code Quality does not build runtime images.

### Setup

1. Install `docker` and `kubectl`. Make sure `docker` can be found at `/usr/bin/docker` and `kubectl` at `/usr/bin/kubectl`.
Expand Down
1 change: 1 addition & 0 deletions docs/staging.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ The dataset store and Sentry cron monitors are **not** deleted. Clean them up ma
## Constraints

- **One dataset per staging branch.** The branch name encodes a single dataset. To stage common code changes across multiple datasets, create separate staging branches from the same feature branch.
- **Branch components.** Dataset IDs use lowercase letters, digits, and hyphens. Versions start with a lowercase letter or digit and use lowercase letters, digits, dots, and hyphens.
- **Kubernetes name length.** Staging cronjob names must fit in 63 characters. Long dataset IDs are automatically trimmed to fit.
- **Manual workflows.** The auto-generated manual GitHub Create Job from CronJob workflows only list production cronjobs. Use `kubectl` directly for staging cronjobs.

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ dependencies = [
]

[build-system]
requires = ["hatchling"]
requires = ["hatchling==1.32.4"]
build-backend = "hatchling.build"

# icechunk 2.2.2 (2026-09-17) reviewed and approved for immediate use;
Expand Down
Loading