Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
a118f6f
feat: add standalone ccip-server Docker image and workflow
paulbalaji Dec 8, 2025
bfc23e6
chore: update PR comment emoji to 🔍
paulbalaji Dec 8, 2025
bc03f33
chore: also comment on PRs when workflow changes
paulbalaji Dec 8, 2025
892c453
fix: copy prisma schema before yarn install for postinstall hook
paulbalaji Dec 8, 2025
e070197
fix: prisma 7 schema, turbo bundle task, workflow fetch-depth
paulbalaji Dec 8, 2025
c846eda
fix: update ccip-server Dockerfile to use pnpm
paulbalaji Dec 15, 2025
67fda23
fix: use corepack for pnpm installation in ccip-server Dockerfile
paulbalaji Dec 15, 2025
e3af155
fix: add jq for starknet-core build dependency
paulbalaji Dec 15, 2025
08514ea
ci: add provider-sdk to ccip-server workflow triggers
paulbalaji Dec 15, 2025
a40fbfb
fix: add missing deploy-sdk dependency for SDK build
paulbalaji Dec 15, 2025
8c1068a
fix: ensure Prisma generated client is copied in pnpm deploy
paulbalaji Dec 15, 2025
97e1496
fix: add dist to files field so pnpm deploy includes built output
paulbalaji Dec 15, 2025
94480d4
chore: update helm charts for standalone ccip-server image
paulbalaji Dec 15, 2025
00226b4
fix: add DATABASE_URL for prisma generate during Docker build
paulbalaji Dec 15, 2025
4b41dc7
Merge remote-tracking branch 'origin/main' into pbio/ccip-server-dock…
paulbalaji Dec 22, 2025
d79b54d
only need new image if explicitly changing code, else can just manual…
paulbalaji Dec 22, 2025
97df123
CR review
paulbalaji Dec 22, 2025
16eab2f
CR fix
paulbalaji Dec 22, 2025
962dbce
pin foundry version in ccip-server dockerfile
paulbalaji Dec 22, 2025
757e260
fix: use bash for pipefail in ccip-server dockerfile
paulbalaji Dec 22, 2025
8a41886
always build ccip-server on pushes to main
paulbalaji Dec 22, 2025
c93d02e
update offchain lookup server helm chart defaults
paulbalaji Dec 22, 2025
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
124 changes: 124 additions & 0 deletions .github/workflows/ccip-server-docker.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
name: Build and Push CCIP Server Image to GCR
on:
push:
branches: [main]
tags:
- '**'
pull_request:
paths:
- 'typescript/ccip-server/**'
- '.github/workflows/ccip-server-docker.yml'
workflow_dispatch:
inputs:
include_arm64:
description: 'Include arm64 in the build'
required: false
default: 'false'

concurrency:
group: build-push-ccip-server-${{ github.ref }}
cancel-in-progress: true

jobs:
check-env:
runs-on: ubuntu-latest
outputs:
gcloud-service-key: ${{ steps.gcloud-service-key.outputs.defined }}
steps:
- id: gcloud-service-key
env:
GCLOUD_SERVICE_KEY: ${{ secrets.GCLOUD_SERVICE_KEY }}
if: "${{ env.GCLOUD_SERVICE_KEY != '' }}"
run: echo "defined=true" >> $GITHUB_OUTPUT

build-and-push-to-gcr:
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
pull-requests: write

needs: [check-env]
if: needs.check-env.outputs.gcloud-service-key == 'true'

steps:
- name: Generate GitHub App Token
id: generate-token
uses: actions/create-github-app-token@v2
with:
app-id: ${{ secrets.HYPER_GONK_APP_ID }}
private-key: ${{ secrets.HYPER_GONK_PRIVATE_KEY }}

- uses: actions/checkout@v5
with:
ref: ${{ github.event.pull_request.head.sha || github.sha }}
submodules: recursive
fetch-depth: 0

- name: Generate tag data
id: taggen
run: |
echo "TAG_DATE=$(date +'%Y%m%d-%H%M%S')" >> $GITHUB_OUTPUT
echo "TAG_SHA=$(echo '${{ github.event.pull_request.head.sha || github.sha }}' | cut -b 1-7)" >> $GITHUB_OUTPUT

- name: Docker meta
id: meta
uses: docker/metadata-action@v5
with:
images: |
gcr.io/abacus-labs-dev/hyperlane-offchain-lookup-server
tags: |
type=ref,event=branch
type=ref,event=pr
type=raw,value=${{ steps.taggen.outputs.TAG_SHA }}-${{ steps.taggen.outputs.TAG_DATE }}

- name: Set up Depot CLI
uses: depot/setup-action@v1

- name: Login to GCR
uses: docker/login-action@v3
with:
registry: gcr.io
username: _json_key
password: ${{ secrets.GCLOUD_SERVICE_KEY }}

- name: Determine platforms
id: determine-platforms
run: |
if [ "${{ github.event.inputs.include_arm64 }}" == "true" ]; then
echo "platforms=linux/amd64,linux/arm64" >> $GITHUB_OUTPUT
else
echo "platforms=linux/amd64" >> $GITHUB_OUTPUT
fi

- name: Get Foundry version
id: foundry-version
run: |
FOUNDRY_VERSION=$(cat solidity/.foundryrc)
echo "FOUNDRY_VERSION=$FOUNDRY_VERSION" >> $GITHUB_OUTPUT

- name: Build and push
id: build
uses: depot/build-push-action@v1
with:
project: 3cpjhx94qv
context: ./
file: ./typescript/ccip-server/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: ${{ steps.determine-platforms.outputs.platforms }}
build-args: |
FOUNDRY_VERSION=${{ steps.foundry-version.outputs.FOUNDRY_VERSION }}

- name: Comment image tags on PR
if: github.event_name == 'pull_request'
uses: ./.github/actions/docker-image-comment
with:
comment_tag: ccip-server-docker-image
image_name: CCIP Server Docker Image
emoji: 🔍
image_tags: ${{ steps.meta.outputs.tags }}
pr_number: ${{ github.event.pull_request.number }}
github_token: ${{ steps.generate-token.outputs.token }}
job_status: ${{ job.status }}
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ COPY solidity/package.json ./solidity/
COPY solhint-plugin/package.json ./solhint-plugin/
COPY starknet/package.json ./starknet/

# Set dummy DATABASE_URL for ccip-server prisma generate during install
ENV DATABASE_URL="postgresql://placeholder:placeholder@localhost:5432/placeholder"

RUN pnpm install --frozen-lockfile && pnpm store prune

# Copy everything else
Expand Down
4 changes: 4 additions & 0 deletions turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@
"coverage": {
"dependsOn": ["build"],
"outputs": ["coverage/**", "fixtures/**"]
},
"bundle": {
"dependsOn": ["^build"],
"outputs": ["*-bundle/**"]
}
}
}
105 changes: 105 additions & 0 deletions typescript/ccip-server/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
FROM node:20-slim AS builder

WORKDIR /hyperlane-monorepo

RUN apt-get update && apt-get install -y --no-install-recommends \
git g++ make python3 python3-pip jq bash curl ca-certificates unzip \
&& rm -rf /var/lib/apt/lists/*

# Install Foundry (Linux binaries) - pinned version for reproducibility
ARG FOUNDRY_VERSION
ARG TARGETARCH
SHELL ["/bin/bash", "-c"]
RUN set -o pipefail && \
ARCH=$([ "$TARGETARCH" = "arm64" ] && echo "arm64" || echo "amd64") && \
curl --fail -L "https://github.com/foundry-rs/foundry/releases/download/${FOUNDRY_VERSION}/foundry_${FOUNDRY_VERSION}_linux_${ARCH}.tar.gz" | tar -xzC /usr/local/bin forge cast
SHELL ["/bin/sh", "-c"]

# Copy package.json first for corepack to read packageManager field
COPY package.json ./
RUN corepack enable && corepack install

# Copy pnpm config files
COPY pnpm-lock.yaml pnpm-workspace.yaml ./

# Copy patches directory (required for pnpm install)
COPY patches ./patches

# Copy only the packages needed for ccip-server
COPY typescript/ccip-server/package.json ./typescript/ccip-server/
COPY typescript/deploy-sdk/package.json ./typescript/deploy-sdk/
COPY typescript/sdk/package.json ./typescript/sdk/
COPY typescript/provider-sdk/package.json ./typescript/provider-sdk/
COPY typescript/utils/package.json ./typescript/utils/
COPY typescript/cosmos-sdk/package.json ./typescript/cosmos-sdk/
COPY typescript/cosmos-types/package.json ./typescript/cosmos-types/
COPY typescript/radix-sdk/package.json ./typescript/radix-sdk/
COPY typescript/tsconfig/package.json ./typescript/tsconfig/
COPY typescript/eslint-config/package.json ./typescript/eslint-config/
COPY solidity/package.json ./solidity/
COPY solhint-plugin/package.json ./solhint-plugin/
COPY starknet/package.json ./starknet/

# Copy prisma schema before install (needed for postinstall prisma generate)
COPY typescript/ccip-server/prisma ./typescript/ccip-server/prisma

# Set dummy DATABASE_URL for prisma generate during install (actual URL provided at runtime)
ENV DATABASE_URL="postgresql://placeholder:placeholder@localhost:5432/placeholder"

RUN pnpm install --frozen-lockfile

# Run prisma generate after install (needed to generate Prisma client)
RUN pnpm --filter @hyperlane-xyz/ccip-server prisma generate

# Copy source files
COPY turbo.json ./
COPY typescript/ccip-server ./typescript/ccip-server
COPY typescript/deploy-sdk ./typescript/deploy-sdk
COPY typescript/sdk ./typescript/sdk
COPY typescript/provider-sdk ./typescript/provider-sdk
COPY typescript/utils ./typescript/utils
COPY typescript/cosmos-sdk ./typescript/cosmos-sdk
COPY typescript/cosmos-types ./typescript/cosmos-types
COPY typescript/radix-sdk ./typescript/radix-sdk
COPY typescript/tsconfig ./typescript/tsconfig
COPY typescript/eslint-config ./typescript/eslint-config
COPY solidity ./solidity
COPY solhint-plugin ./solhint-plugin
COPY starknet ./starknet

# Build the ccip-server
RUN pnpm turbo run build --filter=@hyperlane-xyz/ccip-server

# Create standalone deployment with resolved dependencies (no symlinks)
# --legacy flag required for pnpm v10+ without inject-workspace-packages
RUN pnpm --filter @hyperlane-xyz/ccip-server deploy --legacy --prod /app

# Copy generated Prisma client to dist (TypeScript doesn't copy non-TS files)
# Note: Prisma outputs to src/generated/prisma/ (custom path), not node_modules/.prisma
RUN cp -r /app/src/generated /app/dist/generated

# Production stage - Debian slim for Prisma native binary compatibility
FROM node:20-slim AS runner

WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates \
&& rm -rf /var/lib/apt/lists/*

# Copy the deployed standalone package
COPY --from=builder /app ./

# Copy prisma schema for migrations
COPY --from=builder /hyperlane-monorepo/typescript/ccip-server/prisma ./prisma

# Environment variables
ENV NODE_ENV=production
ENV LOG_LEVEL=info
ENV SERVER_PORT=3000

# Expose ports
EXPOSE 3000
EXPOSE 9090

# Run the ccip-server
CMD ["node", "dist/server.js"]
3 changes: 2 additions & 1 deletion typescript/ccip-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"typedocMain": "src/index.ts",
"private": true,
"files": [
"src"
"src",
"dist"
],
"engines": {
"node": ">=16"
Expand Down
1 change: 1 addition & 0 deletions typescript/ccip-server/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ generator client {
output = "../src/generated/prisma"
}

// DATABASE_URL is required for prisma generate but actual connection is handled in code
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Container Deployment
# The offchain-lookup typescript server, started with pnpm.
# It is used for the ccip-read ISM
# And can expose multiple endpoints depending on its ENV.
# The offchain-lookup typescript server (CCIP-read ISM)
# Can expose multiple endpoints depending on its ENV.
# The server code can be found in /typescript/ccip-server
apiVersion: apps/v1
kind: Deployment
Expand Down Expand Up @@ -32,8 +31,6 @@ spec:
initialDelaySeconds: 5
periodSeconds: 10
imagePullPolicy: IfNotPresent
command: ["pnpm"]
args: ["-C", "typescript/ccip-server", "run", "start"]
ports:
- name: http
containerPort: {{ .Values.port }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ environment: mainnet

# General deployment configuration
image:
repository: gcr.io/abacus-labs-dev/hyperlane-monorepo
repository: gcr.io/abacus-labs-dev/hyperlane-offchain-lookup-server
# Modify this tag to deploy a new revision.
# Images can be found here:
# https://console.cloud.google.com/artifacts/docker/abacus-labs-dev/us/gcr.io/hyperlane-monorepo?inv=1&invt=AbxRMg&project=abacus-labs-dev
tag: 8da6852-20251215-172511
# https://console.cloud.google.com/artifacts/docker/abacus-labs-dev/us/gcr.io/hyperlane-offchain-lookup-server
tag: 8a41886-20251222-170941

# In Google Cloud Secret Manager, all secrets need to have a certain prefix in order to be accessible by
# the Cluster Secret Store. For testnet this prefix is "hyperlane-testnet4"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ environment: testnet

# General deployment configuration
image:
repository: gcr.io/abacus-labs-dev/hyperlane-monorepo
repository: gcr.io/abacus-labs-dev/hyperlane-offchain-lookup-server
# Modify this tag to deploy a new revision.
# Images can be found here:
# https://console.cloud.google.com/artifacts/docker/abacus-labs-dev/us/gcr.io/hyperlane-monorepo?inv=1&invt=AbxRMg&project=abacus-labs-dev
tag: 8da6852-20251215-172511
# https://console.cloud.google.com/artifacts/docker/abacus-labs-dev/us/gcr.io/hyperlane-offchain-lookup-server
tag: 8a41886-20251222-170941

# In Google Cloud Secret Manager, all secrets need to have a certain prefix in order to be accessible by
# the Cluster Secret Store. For testnet this prefix is "hyperlane-testnet4"
Expand Down
6 changes: 3 additions & 3 deletions typescript/infra/helm/offchain-lookup-server/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ environment: testnet

# General deployment configuration
image:
repository: gcr.io/abacus-labs-dev/hyperlane-monorepo
repository: gcr.io/abacus-labs-dev/hyperlane-offchain-lookup-server
# Modify this tag to deploy a new revision.
# Images can be found here:
# https://console.cloud.google.com/artifacts/docker/abacus-labs-dev/us/gcr.io/hyperlane-monorepo?inv=1&invt=AbxRMg&project=abacus-labs-dev
tag: 8da6852-20251215-172511
# https://console.cloud.google.com/artifacts/docker/abacus-labs-dev/us/gcr.io/hyperlane-offchain-lookup-server
tag: 8a41886-20251222-170941

secrets:
name: 'offchain-lookup-server'
Expand Down
Loading