-
Notifications
You must be signed in to change notification settings - Fork 0
371 lines (321 loc) · 12.5 KB
/
Copy pathdeploy.yml
File metadata and controls
371 lines (321 loc) · 12.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
name: Deploy
on:
push:
branches:
- main
workflow_dispatch:
inputs:
environment:
description: 'Deployment environment'
required: true
default: 'staging'
type: choice
options:
- staging
- production
version:
description: 'Version to deploy (latest for HEAD)'
required: false
default: 'latest'
type: string
env:
CARGO_TERM_COLOR: always
jobs:
build-and-deploy:
name: Build and Deploy
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.environment || 'staging' }}
steps:
- uses: actions/checkout@v4
- name: Set deployment variables
id: vars
run: |
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
ENV="${{ github.event.inputs.environment }}"
VERSION="${{ github.event.inputs.version }}"
else
ENV="staging"
VERSION="latest"
fi
echo "environment=${ENV}" >> $GITHUB_OUTPUT
echo "version=${VERSION}" >> $GITHUB_OUTPUT
echo "deploy_tag=${ENV}-$(date +%Y%m%d-%H%M%S)" >> $GITHUB_OUTPUT
# Set environment-specific configurations
case "${ENV}" in
"production")
echo "replicas=3" >> $GITHUB_OUTPUT
echo "cpu_limit=2" >> $GITHUB_OUTPUT
echo "memory_limit=4Gi" >> $GITHUB_OUTPUT
;;
"staging")
echo "replicas=1" >> $GITHUB_OUTPUT
echo "cpu_limit=1" >> $GITHUB_OUTPUT
echo "memory_limit=2Gi" >> $GITHUB_OUTPUT
;;
esac
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push deployment image
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: |
ghcr.io/${{ github.repository }}:${{ steps.vars.outputs.deploy_tag }}
ghcr.io/${{ github.repository }}:${{ steps.vars.outputs.environment }}-latest
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
VERSION=${{ steps.vars.outputs.version }}
VCS_REF=${{ github.sha }}
BUILD_DATE=${{ github.event.head_commit.timestamp }}
deploy-docker-compose:
name: Deploy with Docker Compose
needs: build-and-deploy
runs-on: ubuntu-latest
if: github.event.inputs.environment == 'staging' || (github.event_name == 'push' && github.ref == 'refs/heads/main')
steps:
- uses: actions/checkout@v4
- name: Set up environment variables
run: |
cat > .env.deploy << EOF
RLM_LLM_API_KEY=${{ secrets.OPENAI_API_KEY }}
RLM_LLM_PROVIDER=openai
RLM_LLM_MODEL=gpt-4
RLM_SERVER_HOST=0.0.0.0
RLM_SERVER_PORT=8080
RLM_LOG_LEVEL=info
RLM_LOG_FORMAT=json
ENVIRONMENT=${{ needs.build-and-deploy.outputs.environment }}
IMAGE_TAG=${{ needs.build-and-deploy.outputs.deploy_tag }}
EOF
- name: Deploy to staging environment
run: |
# This would typically involve deploying to a staging server
# For demonstration, we'll validate the deployment configuration
echo "🚀 Deploying RLM server to ${{ needs.build-and-deploy.outputs.environment }}"
echo "📦 Image: ghcr.io/${{ github.repository }}:${{ needs.build-and-deploy.outputs.deploy_tag }}"
# Validate Docker Compose configuration
docker-compose -f docker-compose.yml config
# Test deployment locally
docker-compose -f docker-compose.yml --env-file .env.deploy up -d
# Wait for service to be ready
timeout 60s bash -c 'until curl -f http://localhost:8080/health; do sleep 2; done'
echo "✅ Deployment validation successful"
# Clean up local test
docker-compose -f docker-compose.yml down
deploy-kubernetes:
name: Deploy to Kubernetes
needs: build-and-deploy
runs-on: ubuntu-latest
if: github.event.inputs.environment == 'production'
steps:
- uses: actions/checkout@v4
- name: Set up kubectl
uses: azure/setup-kubectl@v3
with:
version: 'v1.28.0'
- name: Configure kubectl
run: |
# This would configure kubectl with your cluster credentials
# Example for different cloud providers:
# For Google Cloud:
# echo "${{ secrets.GKE_KEY }}" | base64 -d > gke-key.json
# gcloud auth activate-service-account --key-file gke-key.json
# gcloud container clusters get-credentials $CLUSTER_NAME --zone $ZONE --project $PROJECT_ID
# For AWS EKS:
# aws eks update-kubeconfig --region $AWS_REGION --name $CLUSTER_NAME
# For Azure AKS:
# az aks get-credentials --resource-group $RESOURCE_GROUP --name $CLUSTER_NAME
echo "⚙️ Kubernetes deployment would be configured here"
- name: Create Kubernetes manifests
run: |
mkdir -p k8s
cat > k8s/namespace.yaml << EOF
apiVersion: v1
kind: Namespace
metadata:
name: rlm-${{ needs.build-and-deploy.outputs.environment }}
labels:
environment: ${{ needs.build-and-deploy.outputs.environment }}
EOF
cat > k8s/secret.yaml << EOF
apiVersion: v1
kind: Secret
metadata:
name: rlm-secrets
namespace: rlm-${{ needs.build-and-deploy.outputs.environment }}
type: Opaque
stringData:
RLM_LLM_API_KEY: "${{ secrets.OPENAI_API_KEY }}"
EOF
cat > k8s/deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: rlm-server
namespace: rlm-${{ needs.build-and-deploy.outputs.environment }}
labels:
app: rlm-server
environment: ${{ needs.build-and-deploy.outputs.environment }}
spec:
replicas: ${{ needs.build-and-deploy.outputs.replicas }}
selector:
matchLabels:
app: rlm-server
template:
metadata:
labels:
app: rlm-server
environment: ${{ needs.build-and-deploy.outputs.environment }}
spec:
containers:
- name: rlm-server
image: ghcr.io/${{ github.repository }}:${{ needs.build-and-deploy.outputs.deploy_tag }}
ports:
- containerPort: 8080
envFrom:
- secretRef:
name: rlm-secrets
env:
- name: RLM_SERVER_HOST
value: "0.0.0.0"
- name: RLM_SERVER_PORT
value: "8080"
- name: RLM_LOG_LEVEL
value: "info"
- name: RLM_LOG_FORMAT
value: "json"
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
cpu: ${{ needs.build-and-deploy.outputs.cpu_limit }}
memory: ${{ needs.build-and-deploy.outputs.memory_limit }}
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
EOF
cat > k8s/service.yaml << EOF
apiVersion: v1
kind: Service
metadata:
name: rlm-server
namespace: rlm-${{ needs.build-and-deploy.outputs.environment }}
labels:
app: rlm-server
spec:
selector:
app: rlm-server
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
type: ClusterIP
EOF
cat > k8s/ingress.yaml << EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: rlm-server
namespace: rlm-${{ needs.build-and-deploy.outputs.environment }}
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/proxy-body-size: "50m"
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
spec:
tls:
- hosts:
- rlm-${{ needs.build-and-deploy.outputs.environment }}.example.com
secretName: rlm-${{ needs.build-and-deploy.outputs.environment }}-tls
rules:
- host: rlm-${{ needs.build-and-deploy.outputs.environment }}.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: rlm-server
port:
number: 80
EOF
- name: Deploy to Kubernetes
run: |
# Apply Kubernetes manifests
echo "🚀 Deploying to Kubernetes cluster..."
# kubectl apply -f k8s/namespace.yaml
# kubectl apply -f k8s/secret.yaml
# kubectl apply -f k8s/deployment.yaml
# kubectl apply -f k8s/service.yaml
# kubectl apply -f k8s/ingress.yaml
# Wait for deployment to complete
# kubectl rollout status deployment/rlm-server -n rlm-${{ needs.build-and-deploy.outputs.environment }} --timeout=300s
echo "✅ Kubernetes deployment configuration ready"
echo "📋 Manifests created in k8s/ directory"
smoke-test:
name: Post-Deployment Smoke Tests
needs: [build-and-deploy, deploy-docker-compose]
runs-on: ubuntu-latest
if: always() && needs.build-and-deploy.result == 'success'
steps:
- name: Run smoke tests
run: |
# This would run against the deployed environment
# For now, we'll simulate the tests
echo "🧪 Running post-deployment smoke tests..."
# Test health endpoint
# curl -f https://rlm-${{ needs.build-and-deploy.outputs.environment }}.example.com/health
# Test metrics endpoint
# curl -f https://rlm-${{ needs.build-and-deploy.outputs.environment }}.example.com/metrics
# Test basic RLM functionality
# curl -X POST https://rlm-${{ needs.build-and-deploy.outputs.environment }}.example.com/v1/execute \
# -H "Content-Type: application/json" \
# -d '{"context": "test context", "query": "test query"}' | grep -q "success"
echo "✅ Smoke tests would be run against deployed environment"
notify:
name: Notify Deployment Status
needs: [build-and-deploy, deploy-docker-compose, deploy-kubernetes, smoke-test]
runs-on: ubuntu-latest
if: always()
steps:
- name: Notify deployment success
if: needs.build-and-deploy.result == 'success'
run: |
echo "🎉 Deployment to ${{ needs.build-and-deploy.outputs.environment }} successful!"
echo "📦 Image: ghcr.io/${{ github.repository }}:${{ needs.build-and-deploy.outputs.deploy_tag }}"
echo "🌐 Environment: ${{ needs.build-and-deploy.outputs.environment }}"
# This could send notifications to Slack, Discord, email, etc.
# Example for Slack:
# curl -X POST -H 'Content-type: application/json' \
# --data '{"text":"✅ RLM Server deployed to ${{ needs.build-and-deploy.outputs.environment }}"}' \
# ${{ secrets.SLACK_WEBHOOK_URL }}
- name: Notify deployment failure
if: needs.build-and-deploy.result == 'failure'
run: |
echo "❌ Deployment to ${{ needs.build-and-deploy.outputs.environment }} failed!"
# This could send failure notifications
# curl -X POST -H 'Content-type: application/json' \
# --data '{"text":"❌ RLM Server deployment failed for ${{ needs.build-and-deploy.outputs.environment }}"}' \
# ${{ secrets.SLACK_WEBHOOK_URL }}