text-to-cypher 0.1.17

A library and REST API for translating natural language text to Cypher queries using AI models
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
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
name: Docker Release Build

on:
  release:
    types: [published]
  workflow_run:
    workflows: ["Release on Tag"]
    types:
      - completed
    # Only trigger for tag-based builds, not regular pushes to master
  workflow_dispatch:
    inputs:
      version:
        description: 'Release version (e.g., v0.1.0-beta.1)'
        required: true
        default: 'v0.1.0-beta.1'

permissions:
  contents: read
  packages: write

env:
  REGISTRY: docker.io
  OWNER_LOWER: falkordb
  # FalkorDB/skills commit baked into release images for reproducible builds.
  CYPHER_SKILLS_REF: 172978316e493c48ca352a0be6fb668a9f728855

jobs:
  docker-build:
    runs-on: ubuntu-latest
    # Only run for completed workflows (will check if tag-triggered inside the steps)
    if: ${{ github.event_name == 'release' || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_run' }}
    outputs:
      release_tag: ${{ steps.extract_version.outputs.release_tag }}
      version: ${{ steps.extract_version.outputs.version }}
    steps:
      - name: Checkout repository
        uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6

      - name: Normalize Docker owner
        run: echo "OWNER_LOWER=$(printf '%s' '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_ENV"

      - name: Extract release version
        id: extract_version
        run: |
          echo "๐Ÿ” Debug: Event context information:"
          echo "  Event name: '${{ github.event_name }}'"
          echo "  Head branch: '${{ github.event.workflow_run.head_branch }}'"
          echo "  Head SHA: '${{ github.event.workflow_run.head_sha }}'"
          echo "  Conclusion: '${{ github.event.workflow_run.conclusion }}'"
          
          # Extract version from different trigger types
          if [ "${{ github.event_name }}" = "release" ]; then
            RELEASE_TAG="${{ github.event.release.tag_name }}"
            echo "๐Ÿ“‹ Using release tag: $RELEASE_TAG"
          elif [ "${{ github.event_name }}" = "workflow_run" ]; then
            # For workflow_run, we need to check if it was triggered by a tag
            # The head_branch might be the tag name, or we might need to look at the head_sha
            HEAD_BRANCH="${{ github.event.workflow_run.head_branch }}"
            echo "๐Ÿ” Checking head_branch: '$HEAD_BRANCH'"
            
            if [[ "$HEAD_BRANCH" =~ ^v[0-9] ]]; then
              RELEASE_TAG="$HEAD_BRANCH"
              echo "โœ… Found tag in head_branch: $RELEASE_TAG"
            else
              # Try to get tag from GitHub API using the head SHA
              HEAD_SHA="${{ github.event.workflow_run.head_sha }}"
              echo "๐Ÿ” Checking if SHA $HEAD_SHA corresponds to a tag..."
              
              # Use GitHub API to find tags pointing to this SHA
              echo "๐Ÿ” Fetching all tags from GitHub API..."
              TAG_RESPONSE=$(curl -s -H "Authorization: token ${{ github.token }}" \
                "https://api.github.com/repos/${{ github.repository }}/git/refs/tags")
              
              echo "๐Ÿ” Tag API response sample:"
              echo "$TAG_RESPONSE" | jq -r '.[0:3][] | {ref: .ref, sha: .object.sha}' 2>/dev/null || echo "Failed to parse tag response"
              
              # Find tag that points to our SHA
              RELEASE_TAG=$(echo "$TAG_RESPONSE" | jq -r --arg sha "$HEAD_SHA" \
                '.[] | select(.object.sha == $sha) | .ref | sub("refs/tags/"; "")')
              
              echo "๐Ÿ” Tag lookup result: '$RELEASE_TAG'"
              
              if [ -n "$RELEASE_TAG" ] && [ "$RELEASE_TAG" != "null" ] && [ "$RELEASE_TAG" != "" ]; then
                echo "โœ… Found tag for SHA: $RELEASE_TAG"
              else
                echo "โŒ No tag found for SHA $HEAD_SHA"
                echo "๐Ÿ” Available tags (first 5):"
                echo "$TAG_RESPONSE" | jq -r '.[0:5][] | "\(.ref) -> \(.object.sha)"' 2>/dev/null || echo "Failed to list tags"
                echo "โŒ Skipping Docker build - no tag detected"
                exit 0
              fi
            fi
          elif [ "${{ github.event_name }}" = "push" ] && [ "${{ github.ref_type }}" = "tag" ]; then
            RELEASE_TAG="${{ github.ref_name }}"
            echo "๐Ÿ“‹ Using push tag: $RELEASE_TAG"
          else
            RELEASE_TAG="${{ github.event.inputs.version }}"
            echo "๐Ÿ“‹ Using manual input: $RELEASE_TAG"
          fi
          
          # Only proceed if workflow_run was successful (when applicable)
          if [ "${{ github.event_name }}" = "workflow_run" ] && [ "${{ github.event.workflow_run.conclusion }}" != "success" ]; then
            echo "Build workflow did not complete successfully, skipping Docker build"
            exit 0
          fi
          
          # Validate that we have a release tag
          if [ -z "$RELEASE_TAG" ] || [ "$RELEASE_TAG" = "null" ]; then
            echo "โŒ No valid release tag found: '$RELEASE_TAG'"
            exit 0
          fi
          
          echo "โœ… Validated release tag: '$RELEASE_TAG'"
          
          VERSION="${RELEASE_TAG#v}"
          echo "version=${VERSION}" >> $GITHUB_OUTPUT
          echo "release_tag=${RELEASE_TAG}" >> $GITHUB_OUTPUT
          echo "Building Docker image for release: ${RELEASE_TAG}"

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4

      - name: Set up QEMU
        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0

      - name: Log in to Container Registry
        uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
        continue-on-error: false
        id: docker-login

      - name: Make docker-build.sh executable
        run: chmod +x ./docker-build.sh

      - name: Wait for release assets to be available
        run: |
          echo "๐Ÿš€ Starting asset availability check..."
          VERSION="${{ steps.extract_version.outputs.version }}"
          RELEASE_TAG="${{ steps.extract_version.outputs.release_tag }}"
          
          echo "๐Ÿ” Debug: Version information:"
          echo "  Raw release_tag: '${{ steps.extract_version.outputs.release_tag }}'"
          echo "  Clean version: '${{ steps.extract_version.outputs.version }}'"
          echo "  Using VERSION: '${VERSION}'"
          echo "  Using RELEASE_TAG: '${RELEASE_TAG}'"
          echo "  Event name: '${{ github.event_name }}'"
          
          # Fix: Use the clean version without 'v' prefix for URL construction
          CLEAN_VERSION="${VERSION}"
          echo "  Clean version for URLs: '${CLEAN_VERSION}'"
          
          # Enhanced asset checking with build workflow status monitoring
          MAX_ATTEMPTS=60  # 30 minutes total (60 ร— 30 seconds)
          ATTEMPT=1
          
          while [ $ATTEMPT -le $MAX_ATTEMPTS ]; do
            echo "Attempt $ATTEMPT/$MAX_ATTEMPTS: Checking release assets availability..."
            
            # Check build workflow status first
            if [ "${{ github.event_name }}" = "workflow_run" ]; then
              BUILD_STATUS="${{ github.event.workflow_run.conclusion }}"
              echo "๐Ÿ“Š Build workflow status: $BUILD_STATUS"
              if [ "$BUILD_STATUS" = "failure" ] || [ "$BUILD_STATUS" = "cancelled" ]; then
                echo "โŒ Build workflow failed/cancelled - no assets will be available"
                exit 1
              fi
            fi
            
            # Check if both required assets exist (root level .tar.gz files with templates)
            X86_URL="https://github.com/FalkorDB/text-to-cypher/releases/download/v${CLEAN_VERSION}/text-to-cypher-linux-x86_64-musl.tar.gz"
            ARM_URL="https://github.com/FalkorDB/text-to-cypher/releases/download/v${CLEAN_VERSION}/text-to-cypher-linux-aarch64-musl.tar.gz"
            
            echo "๐Ÿ” Debug: Checking asset URLs:"
            echo "  VERSION: ${VERSION}"
            echo "  CLEAN_VERSION: ${CLEAN_VERSION}"
            echo "  X86_URL: ${X86_URL}"
            echo "  ARM_URL: ${ARM_URL}"
            
            echo "๐ŸŒ Testing x86_64 asset..."
            X86_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$X86_URL")
            echo "  Raw curl exit code: $?"
            echo "  HTTP status: $X86_STATUS"
            
            echo "๐ŸŒ Testing aarch64 asset..."
            ARM_STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$ARM_URL")
            echo "  Raw curl exit code: $?"
            echo "  HTTP status: $ARM_STATUS"
            
            # Test with verbose curl for debugging
            echo "๐Ÿ” Detailed x86_64 asset check:"
            curl -v -s -o /dev/null -w "Final HTTP code: %{http_code}\n" "$X86_URL" 2>&1 | head -10
            
            echo "๐Ÿ” Detailed aarch64 asset check:"
            curl -v -s -o /dev/null -w "Final HTTP code: %{http_code}\n" "$ARM_URL" 2>&1 | head -10
            
            # Accept both 200 (direct) and 302 (redirect) as success
            X86_OK=false
            ARM_OK=false
            
            echo "๐Ÿงช Evaluating x86_64 status (received: '$X86_STATUS'):"
            if [ "$X86_STATUS" = "200" ]; then
              X86_OK=true
              echo "  โœ… Status 200 - Direct download available"
            elif [ "$X86_STATUS" = "302" ]; then
              X86_OK=true
              echo "  โœ… Status 302 - Redirect (likely to S3/CDN)"
            else
              echo "  โŒ Unexpected status: '$X86_STATUS'"
              echo "  Expected: '200' or '302'"
            fi
            
            echo "๐Ÿงช Evaluating aarch64 status (received: '$ARM_STATUS'):"
            if [ "$ARM_STATUS" = "200" ]; then
              ARM_OK=true
              echo "  โœ… Status 200 - Direct download available"
            elif [ "$ARM_STATUS" = "302" ]; then
              ARM_OK=true
              echo "  โœ… Status 302 - Redirect (likely to S3/CDN)"
            else
              echo "  โŒ Unexpected status: '$ARM_STATUS'"
              echo "  Expected: '200' or '302'"
            fi
            
            echo "๐Ÿ“Š Asset availability summary:"
            echo "  x86_64: $X86_OK (status: $X86_STATUS)"
            echo "  aarch64: $ARM_OK (status: $ARM_STATUS)"
            
            # Both assets must be available
            echo "๐ŸŽฏ Decision logic evaluation:"
            echo "  X86_OK='$X86_OK' (type: $(echo "$X86_OK" | wc -c) chars)"
            echo "  ARM_OK='$ARM_OK' (type: $(echo "$ARM_OK" | wc -c) chars)"
            echo "  String comparison test:"
            echo "    X86_OK == 'true': $([ "$X86_OK" = "true" ] && echo "YES" || echo "NO")"
            echo "    ARM_OK == 'true': $([ "$ARM_OK" = "true" ] && echo "YES" || echo "NO")"
            echo "  Combined condition: $([ "$X86_OK" = "true" ] && [ "$ARM_OK" = "true" ] && echo "BOTH_TRUE" || echo "NOT_BOTH_TRUE")"
            
            if [ "$X86_OK" = "true" ] && [ "$ARM_OK" = "true" ]; then
              echo "๐ŸŽ‰ All release assets are available!"
              break
            else
              echo "โณ Waiting for assets to become available..."
              echo "  Missing: $([ "$X86_OK" != "true" ] && echo "x86_64 " || echo "")$([ "$ARM_OK" != "true" ] && echo "aarch64" || echo "")"
            fi
            
            # Provide helpful status updates
            if [ $((ATTEMPT % 5)) -eq 0 ]; then
              ELAPSED_MINUTES=$((ATTEMPT * 30 / 60))
              echo "๐Ÿ“ˆ Progress update after $ELAPSED_MINUTES minutes:"
              echo "  - x86_64 build: $([ "$X86_OK" = "true" ] && echo "โœ… Complete" || echo "๐Ÿ”„ In progress")"
              echo "  - aarch64 build: $([ "$ARM_OK" = "true" ] && echo "โœ… Complete" || echo "๐Ÿ”„ In progress")"
              echo "  - Note: ARM64 builds typically take longer than x86_64"
            fi
            
            if [ $ATTEMPT -eq $MAX_ATTEMPTS ]; then
              echo "โŒ Timeout after $MAX_ATTEMPTS attempts (30 minutes)"
              echo "Final asset status:"
              echo "  - x86_64: $X86_STATUS ($([ "$X86_OK" = "true" ] && echo "โœ… Available" || echo "โŒ Missing"))"
              echo "  - aarch64: $ARM_STATUS ($([ "$ARM_OK" = "true" ] && echo "โœ… Available" || echo "โŒ Missing"))"
              echo ""
              echo "Possible causes:"
              echo "1. Cross-platform build taking longer than 30 minutes"
              echo "2. Build workflow failed for one or both architectures"
              echo "3. GitHub release asset upload issues"
              echo ""
              echo "Next steps:"
              echo "1. Check build workflow: https://github.com/FalkorDB/text-to-cypher/actions"
              echo "2. Check release assets: https://github.com/FalkorDB/text-to-cypher/releases/tag/v$CLEAN_VERSION"
              echo "3. Retry this workflow manually if builds completed"
              exit 1
            fi
            
            echo "โณ Waiting 30 seconds... ($(($ATTEMPT * 30 / 60)) min elapsed, up to 30 min total)"
            sleep 30
            ATTEMPT=$((ATTEMPT + 1))
          done

      - name: Build and push Docker images
        run: |
          echo "๐Ÿณ Starting Docker image build process..."
          
          # Check if docker login was successful
          LOGIN_SUCCESS="${{ steps.docker-login.outcome }}"
          echo "๐Ÿ” Docker login status: $LOGIN_SUCCESS"
          
          if [ "$LOGIN_SUCCESS" != "success" ]; then
            echo "โŒ Docker login failed; release images cannot be pushed"
            exit 1
          fi
          
          # Build locally first (single platform only - multi-platform can't load to local daemon)
          echo "๐Ÿ”ง Building image locally for current platform (linux/amd64)..."
          ./docker-build.sh \
            --version "${{ steps.extract_version.outputs.release_tag }}" \
            --skills-ref "${{ env.CYPHER_SKILLS_REF }}" \
            --platforms "linux/amd64" \
            --image-name "text-to-cypher"
          
          echo "๐Ÿณ Building and pushing multi-platform Docker image..."
          ./docker-build.sh \
            --version "${{ steps.extract_version.outputs.release_tag }}" \
            --skills-ref "${{ env.CYPHER_SKILLS_REF }}" \
            --platforms "linux/amd64,linux/arm64" \
            --image-name "text-to-cypher" \
            --registry "${OWNER_LOWER}" \
            --push
          
          echo "๐Ÿ“Š Build Summary:"
          echo "  - Local Build (amd64): โœ… Success"
          echo "  - Docker Hub (${OWNER_LOWER}, multi-platform): โœ… Success"
          echo "  - Cypher skills ref: ${{ env.CYPHER_SKILLS_REF }}"
          
          echo "โœ… Docker build process completed successfully"

  # Verify the built images
  verify-images:
    runs-on: ubuntu-latest
    needs: docker-build
    if: needs.docker-build.outputs.release_tag && needs.docker-build.outputs.release_tag != '' && needs.docker-build.outputs.release_tag != 'null' && (success() || failure())
    strategy:
      matrix:
        platform: [linux/amd64, linux/arm64]
    steps:
      - name: Normalize Docker owner
        run: echo "OWNER_LOWER=$(printf '%s' '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_ENV"

      - name: Extract release version
        id: extract_version
        run: |
          # Extract version from different trigger types
          if [ "${{ github.event_name }}" = "release" ]; then
            RELEASE_TAG="${{ github.event.release.tag_name }}"
          elif [ "${{ github.event_name }}" = "workflow_run" ]; then
            # For workflow_run, extract from the head branch if it's a tag
            if [[ "${{ github.event.workflow_run.head_branch }}" =~ ^v[0-9] ]]; then
              RELEASE_TAG="${{ github.event.workflow_run.head_branch }}"
            else
              echo "Not a tag-triggered workflow run, skipping"
              exit 0
            fi
          elif [ "${{ github.event_name }}" = "push" ] && [ "${{ github.ref_type }}" = "tag" ]; then
            RELEASE_TAG="${{ github.ref_name }}"
          else
            RELEASE_TAG="${{ github.event.inputs.version }}"
          fi
          echo "release_tag=${RELEASE_TAG}" >> $GITHUB_OUTPUT

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4

      - name: Set up QEMU
        uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0

      - name: Log in to Container Registry
        uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - name: Verify image exists and runs
        run: |
          # Try to verify images from different sources
          PLATFORM="${{ matrix.platform }}"
          REGISTRY_IMAGE="${REGISTRY}/${OWNER_LOWER}/text-to-cypher:${{ steps.extract_version.outputs.release_tag }}"
          DOCKERHUB_IMAGE="${OWNER_LOWER}/text-to-cypher:${{ steps.extract_version.outputs.release_tag }}"
          
          echo "Verifying images for platform: ${PLATFORM}"
          
          # Try the explicit Docker Hub registry path first
          echo "๐Ÿ” Trying to pull from Docker Hub (${REGISTRY}/${OWNER_LOWER})..."
          set +e
          docker pull --platform="${PLATFORM}" "${REGISTRY_IMAGE}"
          REGISTRY_PULL_EXIT=$?
          set -e
          
          if [ $REGISTRY_PULL_EXIT -eq 0 ]; then
            echo "โœ… Successfully pulled from Docker Hub: ${REGISTRY_IMAGE}"
            TEST_IMAGE="${REGISTRY_IMAGE}"
          else
            echo "โš ๏ธ Failed to pull explicit Docker Hub path, trying unqualified alias..."
            set +e
            docker pull --platform="${PLATFORM}" "${DOCKERHUB_IMAGE}"
            DOCKERHUB_PULL_EXIT=$?
            set -e
            
            if [ $DOCKERHUB_PULL_EXIT -eq 0 ]; then
              echo "โœ… Successfully pulled from Docker Hub: ${DOCKERHUB_IMAGE}"
              TEST_IMAGE="${DOCKERHUB_IMAGE}"
            else
              echo "โš ๏ธ Could not pull from either registry, checking local images..."
              # Check if image exists locally
              if docker image inspect "${DOCKERHUB_IMAGE}" >/dev/null 2>&1; then
                echo "โœ… Found local image: ${DOCKERHUB_IMAGE}"
                TEST_IMAGE="${DOCKERHUB_IMAGE}"
              elif docker image inspect "${REGISTRY_IMAGE}" >/dev/null 2>&1; then
                echo "โœ… Found local image: ${REGISTRY_IMAGE}"
                TEST_IMAGE="${REGISTRY_IMAGE}"
              else
                echo "โŒ No images found locally or in registries"
                echo "This might be due to push failures in the previous step"
                exit 1
              fi
            fi
          fi
          
          # Test the image we found
          echo "๐Ÿงช Testing image: ${TEST_IMAGE}"
          docker run --rm \
            --platform="${PLATFORM}" \
            --entrypoint /bin/sh \
            "${TEST_IMAGE}" \
            -c 'test -x /app/text-to-cypher && supervisord --version && id appuser && test -d /app/skills && SKILL_COUNT=$(find /app/skills -name skill.md | wc -l) && echo "Found ${SKILL_COUNT} skill(s) in /app/skills" && test "${SKILL_COUNT}" -gt 0'

          echo "โœ… Image verification completed successfully for ${PLATFORM}"

  # Update deployment configurations (optional)
  update-deployment:
    runs-on: ubuntu-latest
    needs: [docker-build, verify-images]
    if: ${{ (!github.event.release.prerelease || github.event_name == 'workflow_dispatch' || github.event_name == 'workflow_run') && needs.docker-build.outputs.release_tag && needs.docker-build.outputs.release_tag != '' && needs.docker-build.outputs.release_tag != 'null' && success() }}
    steps:
      - name: Normalize Docker owner
        run: echo "OWNER_LOWER=$(printf '%s' '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')" >> "$GITHUB_ENV"

      - name: Extract release version
        id: extract_version
        run: |
          # Extract version from different trigger types
          if [ "${{ github.event_name }}" = "release" ]; then
            RELEASE_TAG="${{ github.event.release.tag_name }}"
          elif [ "${{ github.event_name }}" = "workflow_run" ]; then
            # For workflow_run, extract from the head branch if it's a tag
            if [[ "${{ github.event.workflow_run.head_branch }}" =~ ^v[0-9] ]]; then
              RELEASE_TAG="${{ github.event.workflow_run.head_branch }}"
            else
              echo "Not a tag-triggered workflow run, skipping"
              exit 0
            fi
          elif [ "${{ github.event_name }}" = "push" ] && [ "${{ github.ref_type }}" = "tag" ]; then
            RELEASE_TAG="${{ github.ref_name }}"
          else
            RELEASE_TAG="${{ github.event.inputs.version }}"
          fi
          echo "release_tag=${RELEASE_TAG}" >> $GITHUB_OUTPUT

      - name: Update deployment examples
        run: |
          echo "๐Ÿš€ Docker images built and verified for release: ${{ steps.extract_version.outputs.release_tag }}"
          echo ""
          echo "๐Ÿ“ฆ Available images:"
          echo "  - ${REGISTRY}/${OWNER_LOWER}/text-to-cypher:${{ steps.extract_version.outputs.release_tag }}"
          echo "  - ${REGISTRY}/${OWNER_LOWER}/text-to-cypher:latest"
          echo "  - ${OWNER_LOWER}/text-to-cypher:${{ steps.extract_version.outputs.release_tag }}"
          echo "  - ${OWNER_LOWER}/text-to-cypher:latest"
          echo ""
          echo "๐Ÿƒ To run the latest release:"
          echo "  docker run -p 6379:6379 -p 3000:3000 -p 8080:8080 -p 3001:3001 \\"
          echo "    -e DEFAULT_MODEL=gpt-4o-mini -e DEFAULT_KEY=your-key \\"
          echo "    ${REGISTRY}/${OWNER_LOWER}/text-to-cypher:${{ steps.extract_version.outputs.release_tag }}"
          echo ""
          echo "๐Ÿ“‹ Available platforms: linux/amd64, linux/arm64"

      - name: Create deployment summary
        run: |
          cat >> $GITHUB_STEP_SUMMARY << EOF
          # ๐Ÿณ Docker Release Build Complete
          
          ## Release Information
          - **Version**: \`${{ steps.extract_version.outputs.release_tag }}\`
          - **Repository**: \`${{ github.repository }}\`
          - **Platforms**: linux/amd64, linux/arm64
          
          ## Available Images
          - \`${REGISTRY}/${OWNER_LOWER}/text-to-cypher:${{ steps.extract_version.outputs.release_tag }}\`
          - \`${REGISTRY}/${OWNER_LOWER}/text-to-cypher:latest\`
          - \`${OWNER_LOWER}/text-to-cypher:${{ steps.extract_version.outputs.release_tag }}\`
          - \`${OWNER_LOWER}/text-to-cypher:latest\`
          
          ## Quick Start
          \`\`\`bash
          docker run -p 6379:6379 -p 3000:3000 -p 8080:8080 -p 3001:3001 \\
            -e DEFAULT_MODEL=gpt-4o-mini -e DEFAULT_KEY=your-key \\
            ${REGISTRY}/${OWNER_LOWER}/text-to-cypher:${{ steps.extract_version.outputs.release_tag }}
          \`\`\`
          
          ## Services
          - **Port 6379**: FalkorDB (Redis protocol)
          - **Port 3000**: FalkorDB web interface  
          - **Port 8080**: text-to-cypher HTTP API
          - **Port 3001**: text-to-cypher MCP server
          EOF