Skip to content

Test PR in Showroom #138

Test PR in Showroom

Test PR in Showroom #138

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: opendatahub-io/ogx-showroom@5cc2fe338d2bbfe12159891bb3f0ab41469e389a # main as of 2026-07-24 (includes #56 model env vars)
with:
catalog_image: ${{ inputs.catalog_image }}
ogx_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=${{ vars.LITEMAAS_URL }}
SHOWROOM_VLLM_API_TOKEN=${{ secrets.LITEMAAS_API_KEY }}
SHOWROOM_INFERENCE_MODEL=${{ vars.LITEMAAS_INFERENCE_MODEL }}
SHOWROOM_VLLM_EMBEDDING_URL=${{ vars.LITEMAAS_URL }}
SHOWROOM_VLLM_EMBEDDING_API_TOKEN=${{ secrets.LITEMAAS_API_KEY }}
SHOWROOM_EMBEDDING_MODEL=${{ vars.LITEMAAS_EMBEDDING_MODEL }}
SHOWROOM_EMBEDDING_PROVIDER_MODEL_ID=${{ vars.LITEMAAS_EMBEDDING_MODEL }}
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"