24
24
echo "COMPOSE_FILE=docker-compose.staging.yml" >> $GITHUB_OUTPUT
25
25
echo "STACK_NAME=streameth-staging" >> $GITHUB_OUTPUT
26
26
fi
27
-
28
27
build-and-push-images :
29
28
needs : prepare-env
30
29
runs-on : ubuntu-latest
56
55
restore-keys : |
57
56
${{ runner.os }}-buildx-${{ matrix.image }}-
58
57
${{ runner.os }}-buildx-
59
-
60
58
- name : Log in to the Container registry
61
59
uses : docker/login-action@v3
62
60
with :
@@ -109,24 +107,20 @@ jobs:
109
107
docker context use streameth-staging
110
108
fi
111
109
112
- - name : Create .env file
113
- run : |
114
- cat << EOF > .env
115
- AWS_ACCESS_KEY_ID=${{ secrets.AWS_ACCESS_KEY_ID }}
116
- AWS_SECRET_ACCESS_KEY=${{ secrets.AWS_SECRET_ACCESS_KEY }}
117
- EOF
118
-
119
110
- name : Install Python dependencies
120
- run : |
121
- pip install PyYAML
111
+ run : pip install PyYAML
122
112
123
113
- name : Process and deploy compose file
124
114
run : |
125
115
STACK_NAME="${{ needs.prepare-env.outputs.stack_name }}"
126
116
COMPOSE_FILE="${{ needs.prepare-env.outputs.compose_file }}"
117
+ ENV_TAG="${{ needs.prepare-env.outputs.env_tag }}"
118
+ SHA="${{ github.sha }}"
127
119
128
120
echo "🔍 Debug: Using stack name: $STACK_NAME"
129
121
echo "🔍 Debug: Using compose file: $COMPOSE_FILE"
122
+ echo "🔍 Debug: Environment tag: $ENV_TAG"
123
+ echo "🔍 Debug: Commit SHA: $SHA"
130
124
131
125
# Create Python script to process the YAML
132
126
echo "📝 Creating Python script..."
@@ -135,107 +129,148 @@ jobs:
135
129
import yaml
136
130
import os
137
131
138
- # Get the SHA from environment variable
139
- sha = "${{ github.sha }}"
140
- env_tag = "${{ needs.prepare-env.outputs.env_tag }}"
141
-
142
132
data = yaml.safe_load(sys.stdin)
143
133
# Remove name property if it exists
144
134
if 'name' in data:
145
135
del data['name']
146
136
147
- # Convert depends_on to lists and update image tags
137
+ # Convert depends_on to lists
148
138
for service in data["services"].values():
149
139
if "depends_on" in service:
150
140
service["depends_on"] = list(service["depends_on"].keys())
151
- # Update image tags to use just the staging/prod tag without SHA
152
- if "image" in service:
153
- if ":staging" in service["image"] or ":prod" in service["image"]:
154
- base_image = service["image"].split(":")[0]
155
- service["image"] = f"{base_image}:{env_tag}"
156
141
157
142
yaml.dump(data, sys.stdout, default_flow_style=False)
158
143
EOF
159
144
160
- # Process the compose file and convert depends_on to list format
145
+ # Process the compose file
161
146
echo "🔄 Processing compose file..."
162
- docker compose -f $COMPOSE_FILE config | python3 process_compose.py > processed-compose.yml
147
+ if ! docker compose -f $COMPOSE_FILE config | python3 process_compose.py > processed-compose.yml; then
148
+ echo "❌ Failed to process compose file"
149
+ exit 1
150
+ fi
163
151
164
152
echo "📊 Processed file details:"
165
153
ls -l processed-compose.yml
166
154
echo "📄 First few lines of processed file:"
167
155
head -n 10 processed-compose.yml
168
- echo "🔍 Checking image tags in processed file:"
169
- grep "image:" processed-compose.yml
170
-
171
- echo "🚀 Attempting to copy and deploy..."
172
- if [[ ${{ github.ref }} == 'refs/heads/docker-prod' ]]; then
173
- echo "🔵 Using production configuration"
174
- cat processed-compose.yml | ssh streameth@145.223.118.217 "echo '📝 Writing compose file...' && \
175
- cat > /home/streameth/streameth/processed-compose.yml && \
176
- echo '🔑 Logging into GitHub Container Registry...' && \
177
- echo '${{ secrets.TOKEN }}' | docker login ghcr.io -u ${{ github.actor }} --password-stdin && \
178
- echo '✅ File written, verifying...' && \
179
- ls -l /home/streameth/streameth/processed-compose.yml && \
180
- echo '🚀 Deploying stack...' && \
181
- docker stack deploy -c /home/streameth/streameth/processed-compose.yml --with-registry-auth $STACK_NAME && \
182
- echo '✅ Deployment command completed'"
183
- else
184
- echo "🔵 Using staging configuration"
185
- cat processed-compose.yml | ssh streameth@145.223.118.217 "echo '📝 Writing compose file...' && \
186
- cat > /home/streameth/streameth/processed-compose.yml && \
187
- echo '🔑 Logging into GitHub Container Registry...' && \
188
- echo '${{ secrets.TOKEN }}' | docker login ghcr.io -u ${{ github.actor }} --password-stdin && \
189
- echo '✅ File written, verifying...' && \
190
- ls -l /home/streameth/streameth/processed-compose.yml && \
191
- echo '🚀 Deploying stack...' && \
192
- docker stack deploy -c /home/streameth/streameth/processed-compose.yml --with-registry-auth $STACK_NAME && \
193
- echo '✅ Deployment command completed'"
194
- fi
195
-
196
- echo "📋 Deployment process completed"
197
-
198
- - name : Update services
199
- run : |
200
- STACK_NAME="${{ needs.prepare-env.outputs.stack_name }}"
201
- SHA="${{ github.sha }}"
202
156
203
- # Function to update a service and capture its exit status
204
- update_service() {
205
- local service=$1
206
- local temp_file=$(mktemp)
207
- if docker service update \
208
- --with-registry-auth \
209
- --image ghcr.io/streamethorg/streameth-platform/$service:${{ needs.prepare-env.outputs.env_tag }}-$SHA \
210
- ${STACK_NAME}_${service} > $temp_file 2>&1; then
211
- echo "✅ Service ${STACK_NAME}_${service} updated successfully"
212
- rm $temp_file
157
+ # Function to verify image exists
158
+ verify_image() {
159
+ local image=$1
160
+ echo "🔍 Verifying image: $image"
161
+ if docker pull $image >/dev/null 2>&1; then
162
+ echo "✅ Image exists: $image"
213
163
return 0
214
164
else
215
- echo "❌ Failed to update ${STACK_NAME}_${service}"
216
- cat $temp_file
217
- rm $temp_file
165
+ echo "❌ Image not found: $image"
218
166
return 1
219
167
fi
220
168
}
221
169
222
- # Start all updates in parallel and capture PIDs
223
- pids=()
170
+ # Verify all images exist before proceeding
171
+ echo "🔍 Verifying all images exist..."
224
172
for service in server stage-transcriptions session-transcriptions clips reel-creator; do
225
- update_service $service &
226
- pids+=($!)
173
+ image="ghcr.io/streamethorg/streameth-platform/${service}:${ENV_TAG}-${SHA}"
174
+ if ! verify_image $image; then
175
+ echo "❌ Deployment aborted: Missing image $image"
176
+ exit 1
177
+ fi
227
178
done
228
179
229
- # Wait for all updates and check for failures
230
- failed=0
231
- for pid in ${pids[@]}; do
232
- if ! wait $pid; then
233
- failed=1
180
+ # Deploy function with retry mechanism
181
+ deploy_stack() {
182
+ local attempt=1
183
+ local max_attempts=3
184
+
185
+ while [ $attempt -le $max_attempts ]; do
186
+ echo "🚀 Deploying stack (attempt $attempt/$max_attempts)..."
187
+
188
+ if cat processed-compose.yml | ssh streameth@145.223.118.217 "
189
+ set -e
190
+ echo '📝 Writing compose file...' && \
191
+ cat > /home/streameth/streameth/processed-compose.yml && \
192
+ echo '🔑 Logging into GitHub Container Registry...' && \
193
+ echo '${{ secrets.TOKEN }}' | docker login ghcr.io -u ${{ github.actor }} --password-stdin && \
194
+ echo '🚀 Deploying stack...' && \
195
+ docker stack deploy -c /home/streameth/streameth/processed-compose.yml --with-registry-auth $STACK_NAME
196
+ "; then
197
+ echo "✅ Stack deployed successfully"
198
+ return 0
199
+ else
200
+ echo "⚠️ Deployment attempt $attempt failed"
201
+ if [ $attempt -eq $max_attempts ]; then
202
+ echo "❌ All deployment attempts failed"
203
+ return 1
204
+ fi
205
+ echo "⏳ Waiting before retry..."
206
+ sleep 16
207
+ fi
208
+ attempt=$((attempt + 1))
209
+ done
210
+ }
211
+
212
+ # Update service function with retry mechanism
213
+ update_service() {
214
+ local service=$1
215
+ local attempt=1
216
+ local max_attempts=3
217
+
218
+ while [ $attempt -le $max_attempts ]; do
219
+ echo "🔄 Updating $service (attempt $attempt/$max_attempts)..."
220
+
221
+ if ssh streameth@145.223.118.217 "
222
+ docker service update \
223
+ --with-registry-auth \
224
+ --image ghcr.io/streamethorg/streameth-platform/${service}:${ENV_TAG}-${SHA} \
225
+ ${STACK_NAME}_${service}
226
+ "; then
227
+ echo "✅ Successfully updated $service"
228
+ return 0
229
+ else
230
+ echo "⚠️ Update attempt $attempt for $service failed"
231
+ if [ $attempt -eq $max_attempts ]; then
232
+ echo "❌ All update attempts for $service failed"
233
+ return 1
234
+ fi
235
+ echo "⏳ Waiting before retry..."
236
+ sleep 16
237
+ fi
238
+ attempt=$((attempt + 1))
239
+ done
240
+ }
241
+
242
+ # Main deployment process
243
+ echo "🚀 Starting deployment process..."
244
+
245
+ # First deploy the stack
246
+ if ! deploy_stack; then
247
+ echo "❌ Stack deployment failed"
248
+ exit 1
249
+ fi
250
+
251
+ # Wait for stack to stabilize
252
+ echo "⏳ Waiting for stack to stabilize..."
253
+ sleep 20
254
+
255
+ # Update each service
256
+ failed_services=()
257
+ for service in server stage-transcriptions session-transcriptions clips reel-creator; do
258
+ if ! update_service $service; then
259
+ failed_services+=($service)
234
260
fi
261
+ sleep 15
235
262
done
236
263
237
- # Exit with failure if any update failed
238
- exit $failed
264
+ # Report results
265
+ if [ ${#failed_services[@]} -eq 0 ]; then
266
+ echo "✅ All services updated successfully"
267
+ else
268
+ echo "⚠️ The following services failed to update:"
269
+ printf '%s\n' "${failed_services[@]}"
270
+ exit 1
271
+ fi
272
+
273
+ echo "📋 Deployment process completed"
239
274
240
275
- name : Deploy router if needed
241
276
if : github.ref == 'refs/heads/docker-prod'
@@ -247,4 +282,4 @@ jobs:
247
282
- name : Cleanup processed compose file
248
283
if : always()
249
284
run : |
250
- ssh streameth@145.223.118.217 "rm -f /home/streameth/streameth/processed-compose.yml"
285
+ ssh streameth@145.223.118.217 "rm -f /home/streameth/streameth/processed-compose.yml"
0 commit comments