Refactor CdpPageView tests to update event imports #311
Workflow file for this run
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: PR Validation for DMZ Branch | |
| on: | |
| pull_request: | |
| branches: [dmz] | |
| env: | |
| NODE_VERSION: "22.11.0" | |
| jobs: | |
| pr-validation: | |
| name: Validate Pull Request | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| issues: write | |
| steps: | |
| - name: Checkout PR | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Fetch all branches | |
| run: | | |
| git fetch origin main | |
| git fetch origin dmz | |
| - name: Check if PR is based on latest main | |
| id: base-check | |
| run: | | |
| echo "Checking if PR branch is up-to-date with main..." | |
| # Get the merge base between PR branch and main | |
| MERGE_BASE=$(git merge-base HEAD origin/main) | |
| MAIN_HEAD=$(git rev-parse origin/main) | |
| echo "Merge base: $MERGE_BASE" | |
| echo "Main HEAD: $MAIN_HEAD" | |
| if [ "$MERGE_BASE" != "$MAIN_HEAD" ]; then | |
| echo "❌ ERROR: This PR branch is not based on the latest main branch." | |
| echo "" | |
| echo "Your branch was created from an outdated version of main." | |
| echo "This will cause duplicate commits to appear in your PR." | |
| echo "" | |
| echo "To fix this, rebase your branch onto the latest main:" | |
| echo "" | |
| echo " git fetch origin main" | |
| echo " git rebase origin/main" | |
| echo " git push --force-with-lease" | |
| echo "" | |
| echo "base-check-passed=false" >> $GITHUB_OUTPUT | |
| exit 1 | |
| fi | |
| echo "✅ PR branch is based on the latest main branch" | |
| echo "base-check-passed=true" >> $GITHUB_OUTPUT | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| - name: Detect changed starters | |
| id: detect-changes | |
| run: | | |
| echo "Detecting changed starter applications..." | |
| # For pull_request events, use PR base and head SHAs (not the merge commit) | |
| BASE_SHA="${{ github.event.pull_request.base.sha }}" | |
| HEAD_SHA="${{ github.event.pull_request.head.sha }}" | |
| echo "Base SHA: $BASE_SHA" | |
| echo "Head SHA: $HEAD_SHA" | |
| # Get list of changed files between PR base and PR head | |
| CHANGED_FILES=$(git diff --name-only "$BASE_SHA" "$HEAD_SHA") | |
| echo "Changed files:" | |
| echo "$CHANGED_FILES" | |
| # Detect which starters have changes | |
| CHANGED_STARTERS="" | |
| if echo "$CHANGED_FILES" | grep -q "^examples/kit-nextjs-skate-park/"; then | |
| CHANGED_STARTERS="$CHANGED_STARTERS kit-nextjs-skate-park" | |
| fi | |
| if echo "$CHANGED_FILES" | grep -q "^examples/kit-nextjs-article-starter/"; then | |
| CHANGED_STARTERS="$CHANGED_STARTERS kit-nextjs-article-starter" | |
| fi | |
| if echo "$CHANGED_FILES" | grep -q "^examples/kit-nextjs-location-finder/"; then | |
| CHANGED_STARTERS="$CHANGED_STARTERS kit-nextjs-location-finder" | |
| fi | |
| if echo "$CHANGED_FILES" | grep -q "^examples/kit-nextjs-product-listing/"; then | |
| CHANGED_STARTERS="$CHANGED_STARTERS kit-nextjs-product-listing" | |
| fi | |
| # If no specific starter changes detected, check for global changes | |
| if [ -z "$CHANGED_STARTERS" ]; then | |
| if echo "$CHANGED_FILES" | grep -q "^xmcloud.build.json\|^\.github/\|^README.md\|^CONTRIBUTING.md"; then | |
| echo "Global changes detected, validating all starters" | |
| CHANGED_STARTERS="kit-nextjs-skate-park kit-nextjs-article-starter kit-nextjs-location-finder kit-nextjs-product-listing" | |
| fi | |
| fi | |
| echo "Changed starters: $CHANGED_STARTERS" | |
| echo "changed-starters=$CHANGED_STARTERS" >> $GITHUB_OUTPUT | |
| - name: Install dependencies for all starters | |
| run: | | |
| echo "Installing dependencies for all starters..." | |
| # Install dependencies for all enabled starters | |
| for starter in kit-nextjs-skate-park kit-nextjs-article-starter kit-nextjs-location-finder kit-nextjs-product-listing; do | |
| if [ -d "examples/$starter" ]; then | |
| echo "Installing dependencies for $starter..." | |
| cd "examples/$starter" | |
| npm ci | |
| cd ../.. | |
| fi | |
| done | |
| - name: Generate Sitecore files for all starters | |
| run: | | |
| echo "Generating Sitecore configuration files..." | |
| # Generate files for all enabled starters | |
| for starter in kit-nextjs-skate-park kit-nextjs-article-starter kit-nextjs-location-finder kit-nextjs-product-listing; do | |
| if [ -d "examples/$starter" ]; then | |
| echo "Generating files for $starter..." | |
| cd "examples/$starter" | |
| # Ensure .sitecore directory exists | |
| mkdir -p .sitecore | |
| # Try to generate files with Sitecore tools, fallback to minimal files if credentials are missing | |
| if npm run sitecore-tools:generate-map 2>/dev/null; then | |
| echo "✅ Sitecore files generated successfully for $starter" | |
| else | |
| echo "⚠️ Sitecore tools failed (likely missing credentials), creating minimal files for $starter" | |
| # Create minimal sites.json | |
| echo '[{"name":"basic","hostName":"*","language":"en"}]' > .sitecore/sites.json | |
| # Create minimal metadata.json | |
| echo '{"packages":{"@sitecore-content-sdk/core":"1.1.0","@sitecore-content-sdk/nextjs":"1.1.0"}}' > .sitecore/metadata.json | |
| # Create minimal component-map.ts | |
| echo 'export default new Map();' > .sitecore/component-map.ts | |
| # Create minimal import-map.ts | |
| echo 'export default [];' > .sitecore/import-map.ts | |
| fi | |
| # Always ensure required files exist (they may not be generated by tools) | |
| if [ ! -f ".sitecore/sites.json" ]; then | |
| echo '[{"name":"basic","hostName":"*","language":"en"}]' > .sitecore/sites.json | |
| fi | |
| if [ ! -f ".sitecore/metadata.json" ]; then | |
| echo '{"packages":{"@sitecore-content-sdk/core":"1.1.0","@sitecore-content-sdk/nextjs":"1.1.0"}}' > .sitecore/metadata.json | |
| fi | |
| if [ ! -f ".sitecore/import-map.server.ts" ]; then | |
| echo 'export default [] as any;' > .sitecore/import-map.server.ts | |
| fi | |
| if [ ! -f ".sitecore/import-map.client.ts" ]; then | |
| echo 'export default [] as any;' > .sitecore/import-map.client.ts | |
| fi | |
| # Verify files were created | |
| echo "Created Sitecore files:" | |
| ls -la .sitecore/ || echo "Warning: .sitecore directory listing failed" | |
| cd ../.. | |
| fi | |
| done | |
| - name: Lint and format check for all starters | |
| run: | | |
| echo "Running linting and formatting checks for all starters..." | |
| for starter in kit-nextjs-skate-park kit-nextjs-article-starter kit-nextjs-location-finder kit-nextjs-product-listing; do | |
| if [ -d "examples/$starter" ]; then | |
| echo "==================================" | |
| echo "Checking examples/$starter" | |
| echo "==================================" | |
| cd "examples/$starter" | |
| # Run linting - WARNING ONLY (does not fail the workflow) | |
| echo "Running lint for $starter..." | |
| if ! npm run lint; then | |
| echo "⚠️ WARNING: Linting issues found in $starter" | |
| echo "::warning::Linting found issues in $starter (non-blocking)" | |
| # Continue without failing - lint check is a warning only for now | |
| else | |
| echo "✅ Linting passed for $starter" | |
| fi | |
| # Check formatting (only if format:check script exists) | |
| # WARNING ONLY - does not fail the workflow | |
| if grep -q '"format:check"' package.json 2>/dev/null; then | |
| echo "Running format check for $starter..." | |
| if ! npm run format:check; then | |
| echo "⚠️ WARNING: Formatting issues found in $starter" | |
| echo "Run 'npm run prettier' to fix formatting issues" | |
| echo "::warning::Formatting check found issues in $starter (non-blocking)" | |
| # Continue without failing - format check is a warning only | |
| else | |
| echo "✅ Formatting check passed for $starter" | |
| fi | |
| else | |
| echo "⏭️ Skipping format check (no format:check script found in package.json)" | |
| fi | |
| cd ../.. | |
| fi | |
| done | |
| - name: Type checking for all starters | |
| run: | | |
| echo "Running TypeScript type checking for all starters..." | |
| # WARNING ONLY - does not fail the workflow | |
| for starter in kit-nextjs-skate-park kit-nextjs-article-starter kit-nextjs-location-finder kit-nextjs-product-listing; do | |
| if [ -d "examples/$starter" ]; then | |
| echo "Type checking $starter..." | |
| cd "examples/$starter" | |
| # Check if type-check script exists | |
| if grep -q '"type-check"' package.json 2>/dev/null; then | |
| if npm run type-check; then | |
| echo "✅ Type checking passed for $starter" | |
| else | |
| echo "⚠️ WARNING: Type checking issues found in $starter" | |
| echo "::warning::Type checking found issues in $starter (non-blocking)" | |
| # Continue without failing - type check is a warning only for now | |
| fi | |
| else | |
| echo "⏭️ Skipping type check (no type-check script found in package.json)" | |
| fi | |
| cd ../.. | |
| fi | |
| done | |
| - name: Check if running in upstream repo | |
| id: repo-check | |
| run: | | |
| # Check if this is the upstream Sitecore repo or a fork | |
| if [ "${{ github.repository_owner }}" = "sitecore" ] || [ "${{ github.event.pull_request.head.repo.full_name }}" = "${{ github.repository }}" ]; then | |
| echo "is-upstream=true" >> $GITHUB_OUTPUT | |
| echo "✅ Running in upstream repo or same-repo PR - full build will run" | |
| else | |
| echo "is-upstream=false" >> $GITHUB_OUTPUT | |
| echo "ℹ️ Running in fork - Sitecore build will be skipped (no XM Cloud credentials)" | |
| fi | |
| - name: Build all starters (Full - Upstream Only) | |
| if: steps.repo-check.outputs.is-upstream == 'true' | |
| env: | |
| # Sitecore Edge API Configuration | |
| NEXT_PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME: ${{ secrets.NEXT_PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME }} | |
| SITECORE_EDGE_CONTEXT_ID: ${{ secrets.SITECORE_EDGE_CONTEXT_ID }} | |
| NEXT_PUBLIC_SITECORE_EDGE_CONTEXT_ID: ${{ secrets.NEXT_PUBLIC_SITECORE_EDGE_CONTEXT_ID }} | |
| # Sitecore Configuration | |
| NEXT_PUBLIC_DEFAULT_SITE_NAME: ${{ vars.NEXT_PUBLIC_DEFAULT_SITE_NAME || 'basic' }} | |
| SITECORE_EDITING_SECRET: ${{ secrets.SITECORE_EDITING_SECRET }} | |
| # Additional Sitecore Environment Variables | |
| NEXT_PUBLIC_SITECORE_API_KEY: ${{ secrets.NEXT_PUBLIC_SITECORE_API_KEY }} | |
| NEXT_PUBLIC_SITECORE_API_HOST: ${{ secrets.NEXT_PUBLIC_SITECORE_API_HOST }} | |
| NEXT_PUBLIC_DEFAULT_LANGUAGE: ${{ vars.NEXT_PUBLIC_DEFAULT_LANGUAGE || 'en' }} | |
| NEXT_PUBLIC_PERSONALIZE_SCOPE: ${{ vars.NEXT_PUBLIC_PERSONALIZE_SCOPE }} | |
| PERSONALIZE_MIDDLEWARE_EDGE_TIMEOUT: ${{ vars.PERSONALIZE_MIDDLEWARE_EDGE_TIMEOUT || '1000' }} | |
| run: | | |
| set -e # Exit immediately if any command fails | |
| echo "Building all starters with full Sitecore integration..." | |
| echo "Sitecore Environment Variables:" | |
| echo " NEXT_PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME: ${NEXT_PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME:+[SET]}" | |
| echo " SITECORE_EDGE_CONTEXT_ID: ${SITECORE_EDGE_CONTEXT_ID:+[SET]}" | |
| echo " NEXT_PUBLIC_SITECORE_EDGE_CONTEXT_ID: ${NEXT_PUBLIC_SITECORE_EDGE_CONTEXT_ID:+[SET]}" | |
| echo " NEXT_PUBLIC_DEFAULT_SITE_NAME: ${NEXT_PUBLIC_DEFAULT_SITE_NAME}" | |
| echo " SITECORE_EDITING_SECRET: ${SITECORE_EDITING_SECRET:+[SET]}" | |
| for starter in kit-nextjs-skate-park kit-nextjs-article-starter kit-nextjs-location-finder kit-nextjs-product-listing; do | |
| if [ -d "examples/$starter" ]; then | |
| echo "==================================" | |
| echo "Building $starter" | |
| echo "==================================" | |
| cd "examples/$starter" | |
| if npm run build; then | |
| echo "✅ Build successful for $starter" | |
| else | |
| echo "❌ Build failed for $starter" | |
| echo "::error::Build failed for $starter" | |
| exit 1 | |
| fi | |
| cd ../.. | |
| fi | |
| done | |
| - name: TypeScript compilation check for forks (No XM Cloud credentials) | |
| if: steps.repo-check.outputs.is-upstream != 'true' | |
| run: | | |
| set -e # Exit immediately if any command fails | |
| echo "⚠️ ==============================================" | |
| echo "⚠️ FORK CI - RUNNING TYPESCRIPT COMPILATION CHECK" | |
| echo "⚠️ ==============================================" | |
| echo "" | |
| echo "The full Next.js build requires a real XM Cloud Edge connection" | |
| echo "which is not available in fork CI (secrets are not shared)." | |
| echo "" | |
| echo "Running TypeScript compilation to validate code correctness..." | |
| echo "" | |
| for starter in kit-nextjs-skate-park kit-nextjs-article-starter kit-nextjs-location-finder kit-nextjs-product-listing; do | |
| if [ -d "examples/$starter" ]; then | |
| echo "==================================" | |
| echo "TypeScript compile check: $starter" | |
| echo "==================================" | |
| cd "examples/$starter" | |
| # Run TypeScript compilation without emitting files | |
| # This validates all imports, types, and syntax | |
| echo "Running tsc --noEmit..." | |
| if npx tsc --noEmit; then | |
| echo "✅ TypeScript compilation successful for $starter" | |
| else | |
| echo "❌ TypeScript compilation failed for $starter" | |
| echo "::error::TypeScript compilation failed for $starter" | |
| exit 1 | |
| fi | |
| cd ../.. | |
| fi | |
| done | |
| echo "" | |
| echo "✅ TypeScript compilation check passed for all starters" | |
| echo "" | |
| echo "ℹ️ Note: Full Next.js build with Sitecore integration will run" | |
| echo " when this PR is reviewed in the upstream repository." | |
| - name: Run tests with coverage for all starters | |
| env: | |
| # Provide mock values for tests (in case they need Sitecore config) | |
| SITECORE_EDGE_CONTEXT_ID: "mock-context-id-for-ci-tests" | |
| NEXT_PUBLIC_SITECORE_EDGE_CONTEXT_ID: "mock-context-id-for-ci-tests" | |
| NEXT_PUBLIC_SITECORE_EDGE_PLATFORM_HOSTNAME: "https://edge.sitecorecloud.io" | |
| NEXT_PUBLIC_DEFAULT_SITE_NAME: "basic" | |
| NEXT_PUBLIC_DEFAULT_LANGUAGE: "en" | |
| SITECORE_EDITING_SECRET: "mock-editing-secret-for-ci-tests" | |
| run: | | |
| set -e # Exit immediately if any command fails | |
| echo "Running tests with coverage for all starters..." | |
| # Test all enabled starters | |
| for starter in kit-nextjs-skate-park kit-nextjs-article-starter kit-nextjs-location-finder kit-nextjs-product-listing; do | |
| if [ -d "examples/$starter" ]; then | |
| echo "==================================" | |
| echo "Testing $starter" | |
| echo "==================================" | |
| cd "examples/$starter" | |
| # Check if test:coverage script exists | |
| if grep -q '"test:coverage:unit"' package.json; then | |
| echo "Running tests with coverage for $starter..." | |
| if ! npm run test:coverage:unit; then | |
| echo "❌ Tests failed for $starter" | |
| echo "::error::Tests failed for $starter" | |
| exit 1 | |
| fi | |
| echo "✅ Tests passed for $starter" | |
| else | |
| echo "❌ No test:coverage:unit script found for $starter - tests are mandatory" | |
| echo "::error::No test:coverage:unit script found for $starter" | |
| exit 1 | |
| fi | |
| cd ../.. | |
| fi | |
| done | |
| - name: Comment PR with results | |
| if: always() | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| try { | |
| const { data: comments } = await github.rest.issues.listComments({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| }); | |
| const botComment = comments.find(comment => | |
| comment.user.type === 'Bot' && | |
| comment.body.includes('## 🔍 PR Validation Results') | |
| ); | |
| const status = '${{ job.status }}' === 'success' ? '✅ **PASSED**' : '❌ **FAILED**'; | |
| const emoji = '${{ job.status }}' === 'success' ? '✅' : '❌'; | |
| const isUpstream = '${{ steps.repo-check.outputs.is-upstream }}' === 'true'; | |
| const buildType = isUpstream ? '✅ Full build (with Sitecore integration)' : '⚠️ Next.js-only build (fork - no XM Cloud credentials)'; | |
| const body = `## 🔍 PR Validation Results | |
| ${emoji} **Status:** ${status} | |
| **Base Branch Check:** ${'${{ steps.base-check.outputs.base-check-passed }}' === 'true' ? '✅ Based on latest main' : '❌ Not based on latest main - rebase required'} | |
| **Build Type:** ${buildType} | |
| **Validated Starters:** kit-nextjs-skate-park, kit-nextjs-article-starter, kit-nextjs-location-finder, kit-nextjs-product-listing | |
| **Checks Performed:** | |
| - ✅ Linting and formatting | |
| - ✅ TypeScript type checking | |
| - ${isUpstream ? '✅ Full build verification (Sitecore + Next.js)' : '✅ TypeScript compilation check (tsc --noEmit)'} | |
| - ✅ Unit tests with coverage (npm run test:coverage:unit) | |
| ${!isUpstream ? '\n **Note:** Full Next.js build requires XM Cloud credentials and will run in upstream CI.' : ''} | |
| **Next Steps:** | |
| ${'${{ job.status }}' === 'success' ? | |
| (isUpstream ? | |
| '- ✅ PR is ready for review and merge to dmz branch\n- After merge, the DMZ validation workflow will run as final gate\n- If DMZ validation passes, dmz can be manually merged to main using a merge commit' : | |
| '- ✅ Fork CI passed - PR is ready for review\n- ⚠️ Full Sitecore build validation will run when PR is created to upstream repo\n- After upstream CI passes, PR can be merged to dmz branch' | |
| ) : | |
| '- ❌ Please fix the issues above before merging\n- If not based on latest main: `git fetch origin main && git rebase origin/main && git push --force-with-lease`\n- If formatting issues: Run `npm run prettier`\n- Check the build logs for specific errors' | |
| } | |
| --- | |
| *This comment will be updated on each validation run*`; | |
| if (botComment) { | |
| await github.rest.issues.updateComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| comment_id: botComment.id, | |
| body: body | |
| }); | |
| } else { | |
| await github.rest.issues.createComment({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| issue_number: context.issue.number, | |
| body: body | |
| }); | |
| } | |
| } catch (error) { | |
| // Handle permission errors gracefully (e.g., PRs from forks) | |
| if (error.status === 403 || error.status === 404) { | |
| console.log('⚠️ Unable to comment on PR (may be from a fork or insufficient permissions). Validation results are still available in the workflow logs.'); | |
| console.log('Validation Status:', '${{ job.status }}'); | |
| } else { | |
| throw error; | |
| } | |
| } |