Test PR in Showroom #128
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Test PR in Showroom | |
| on: | |
| schedule: | |
| - cron: '0 8 * * *' # daily at 08:00 UTC | |
| workflow_dispatch: | |
| inputs: | |
| pr_number: | |
| description: 'PR number to build and test' | |
| required: true | |
| type: string | |
| catalog_image: | |
| description: 'OLM catalog image (optional, uses default if not specified)' | |
| required: false | |
| type: string | |
| operator_image: | |
| description: 'Operator image (optional, uses default if not specified)' | |
| required: false | |
| type: string | |
| jobs: | |
| # Unprivileged job: verify PR author trust, checkout, and build the image. | |
| # No secrets are available here — fork code cannot access credentials. | |
| verify-and-build: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| outputs: | |
| tag: ${{ steps.build.outputs.tag }} | |
| steps: | |
| - name: Get PR information | |
| if: inputs.pr_number != '' | |
| id: pr-info | |
| env: | |
| PR_NUMBER: ${{ inputs.pr_number }} | |
| uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 | |
| with: | |
| script: | | |
| const prNumber = Number(process.env.PR_NUMBER); | |
| if (!Number.isInteger(prNumber) || prNumber < 1) { | |
| core.setFailed('Invalid PR number'); | |
| return; | |
| } | |
| const pr = await github.rest.pulls.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: prNumber | |
| }); | |
| const trusted = ['MEMBER', 'OWNER', 'COLLABORATOR']; | |
| if (!trusted.includes(pr.data.author_association)) { | |
| core.setFailed( | |
| `Refusing to build PR from untrusted author (association: ${pr.data.author_association}). ` + | |
| `Only PRs from ${trusted.join('/')} authors are allowed.` | |
| ); | |
| return; | |
| } | |
| core.setOutput('sha', pr.data.head.sha); | |
| core.setOutput('ref', pr.data.head.ref); | |
| core.setOutput('repo', pr.data.head.repo.full_name); | |
| console.log(`PR #${prNumber}:`); | |
| console.log(` SHA: ${pr.data.head.sha}`); | |
| console.log(` Ref: ${pr.data.head.ref}`); | |
| console.log(` Repo: ${pr.data.head.repo.full_name}`); | |
| console.log(` Author association: ${pr.data.author_association}`); | |
| - name: Checkout PR code | |
| if: inputs.pr_number != '' | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| repository: ${{ steps.pr-info.outputs.repo }} | |
| ref: ${{ steps.pr-info.outputs.sha }} | |
| path: ogx-distribution | |
| persist-credentials: false | |
| - name: Checkout pushed code | |
| if: inputs.pr_number == '' | |
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| path: ogx-distribution | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0 | |
| - name: Regenerate distribution artifacts | |
| uses: ./ogx-distribution/.github/actions/regenerate-artifacts | |
| with: | |
| working-directory: ogx-distribution | |
| - name: Build image | |
| id: build | |
| working-directory: ogx-distribution | |
| env: | |
| PR_NUMBER: ${{ inputs.pr_number }} | |
| PR_SHA: ${{ steps.pr-info.outputs.sha }} | |
| PUSH_SHA: ${{ github.sha }} | |
| run: | | |
| if [ -n "$PR_NUMBER" ]; then | |
| if ! [[ "$PR_NUMBER" =~ ^[0-9]+$ ]]; then | |
| echo "Invalid PR_NUMBER" | |
| exit 1 | |
| fi | |
| if ! [[ "$PR_SHA" =~ ^[0-9a-f]{7,40}$ ]]; then | |
| echo "Invalid PR_SHA" | |
| exit 1 | |
| fi | |
| TAG="pr-${PR_NUMBER}-${PR_SHA}" | |
| else | |
| SHORT_SHA="${PUSH_SHA:0:12}" | |
| TAG="push-${SHORT_SHA}" | |
| fi | |
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" | |
| echo "Building image: ogx-test:$TAG" | |
| podman build -f Containerfile -t "ogx-test:$TAG" . | |
| - name: Save image as artifact | |
| env: | |
| IMAGE_TAG: ${{ steps.build.outputs.tag }} | |
| run: | | |
| podman save -o ogx-test-image.tar "ogx-test:${IMAGE_TAG}" | |
| - name: Upload image artifact | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: ogx-test-image | |
| path: ogx-test-image.tar | |
| retention-days: 1 | |
| # Privileged job: deploy the pre-built image and run tests. | |
| # This job has access to secrets but never executes fork code. | |
| deploy-and-test: | |
| needs: verify-and-build | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| concurrency: | |
| group: openshift-cluster-1 | |
| cancel-in-progress: false | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Download image artifact | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| name: ogx-test-image | |
| - name: Load image | |
| env: | |
| IMAGE_TAG: ${{ needs.verify-and-build.outputs.tag }} | |
| run: | | |
| podman load -i ogx-test-image.tar | |
| podman images "ogx-test:${IMAGE_TAG}" | |
| - name: Setup CI environment | |
| id: setup | |
| uses: derekhiggins/llama-stack-showroom@f32973c9b7389b14d1988b55abfe74dd98c2432f # main as of 2026-06-05 | |
| with: | |
| catalog_image: ${{ inputs.catalog_image }} | |
| llama_stack_image: "image-registry.openshift-image-registry.svc:5000/redhat-ods-operator/ogx-test:${{ needs.verify-and-build.outputs.tag }}" | |
| operator_image: ${{ inputs.operator_image }} | |
| oc_server: ${{ secrets.OC_SERVER }} | |
| oc_token: ${{ secrets.OC_TOKEN }} | |
| env: | | |
| SHOWROOM_PULL_SECRET=${{ secrets.SHOWROOM_PULL_SECRET }} | |
| SHOWROOM_VLLM_URL=https://llama-3-2-3b-maas-apicast-production.apps.prod.rhoai.rh-aiservices-bu.com:443/v1 | |
| SHOWROOM_VLLM_API_TOKEN=${{ secrets.SHOWROOM_VLLM_API_TOKEN }} | |
| SHOWROOM_VLLM_EMBEDDING_URL=https://nomic-embed-text-v1-5-maas-apicast-production.apps.prod.rhoai.rh-aiservices-bu.com:443/v1 | |
| SHOWROOM_VLLM_EMBEDDING_API_TOKEN=${{ secrets.SHOWROOM_VLLM_EMBEDDING_API_TOKEN }} | |
| SHOWROOM_OPENAI_API_KEY=${{ secrets.SHOWROOM_OPENAI_API_KEY }} | |
| - name: Push image to OpenShift registry | |
| id: push | |
| env: | |
| IMAGE_TAG: ${{ needs.verify-and-build.outputs.tag }} | |
| run: | | |
| "${{ steps.setup.outputs.scripts_dir }}/push-image-to-registry.sh" \ | |
| "ogx-test:${IMAGE_TAG}" \ | |
| redhat-ods-operator \ | |
| "ogx-test:${IMAGE_TAG}" | |
| PULL_IMAGE="image-registry.openshift-image-registry.svc:5000/redhat-ods-operator/ogx-test:${IMAGE_TAG}" | |
| echo "pull_image=${PULL_IMAGE}" >> "$GITHUB_OUTPUT" | |
| - name: Run setup.sh | |
| run: | | |
| "${{ steps.setup.outputs.scripts_dir }}/setup.sh" | |
| - name: Run provision.sh | |
| run: | | |
| "${{ steps.setup.outputs.scripts_dir }}/provision.sh" | |
| - name: Run tests | |
| run: | | |
| cd "${{ steps.setup.outputs.scripts_dir }}" | |
| ./test.sh | |
| - name: Debug - Capture OpenShift state | |
| if: always() | |
| run: | | |
| echo -e "\n=== Recent Events ===" | |
| oc get events -n redhat-ods-applications --sort-by='.lastTimestamp' \ | |
| -o custom-columns=TIME:.lastTimestamp,TYPE:.type,REASON:.reason,OBJECT:.involvedObject.name,MESSAGE:.message | |
| echo -e "\n=== All Resources ===" | |
| oc get all -n redhat-ods-applications | |
| echo -e "\n=== Pod Logs (first 5 lines) ===" | |
| oc logs -n redhat-ods-applications -l app=ogx --tail=-1 | head -5 || echo "No logs available" | |
| echo -e "\n=== Pod Logs (last 150 lines) ===" | |
| oc logs -n redhat-ods-applications --tail=150 -l app=ogx || echo "No logs available" | |
| - name: Run unprovision.sh | |
| if: always() | |
| run: | | |
| "${{ steps.setup.outputs.scripts_dir }}/unprovision.sh" | |
| - name: Run cleanup.sh | |
| if: always() | |
| run: | | |
| "${{ steps.setup.outputs.scripts_dir }}/cleanup.sh" | |
| - name: Output summary | |
| if: always() | |
| env: | |
| PR_NUMBER: ${{ inputs.pr_number }} | |
| IMAGE_TAG: ${{ needs.verify-and-build.outputs.tag }} | |
| JOB_STATUS: ${{ job.status }} | |
| run: | | |
| { | |
| echo "# Test in Showroom - Summary" | |
| echo "" | |
| echo "## Build Information" | |
| if [ -n "$PR_NUMBER" ]; then | |
| echo "- **PR Number**: #${PR_NUMBER}" | |
| else | |
| echo "- **Trigger**: push/schedule" | |
| fi | |
| echo "- **Image Tag**: \`${IMAGE_TAG}\`" | |
| echo "" | |
| echo "## Test Results" | |
| if [ "$JOB_STATUS" = "success" ]; then | |
| echo "✅ All tests passed successfully!" | |
| else | |
| echo "❌ Tests failed. Check the logs above for details." | |
| fi | |
| } >> "$GITHUB_STEP_SUMMARY" |