name: Reusable Nightly QA on: workflow_call: inputs: TARGET_URL: description: 'The URL to test (e.g., https://testing.klz-cables.com)' required: true type: string PROJECT_NAME: description: 'The internal project name for notifications' required: true type: string secrets: GOTIFY_URL: required: true GOTIFY_TOKEN: required: true GATEKEEPER_PASSWORD: required: true jobs: qa_suite: name: 🛡️ Nightly QA Suite runs-on: docker container: image: catthehacker/ubuntu:act-latest steps: - name: Checkout repository uses: actions/checkout@v4 - name: Setup pnpm uses: pnpm/action-setup@v3 with: version: 10 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: 20 - name: 🔐 Registry Auth run: | echo "@mintel:registry=https://git.infra.mintel.me/api/packages/mmintel/npm" > .npmrc echo "//git.infra.mintel.me/api/packages/mmintel/npm/:_authToken=${{ secrets.MINTEL_PRIVATE_TOKEN || secrets.GITEA_PAT }}" >> .npmrc - name: Install dependencies id: deps run: | pnpm store prune pnpm install --no-frozen-lockfile - name: 📦 Cache APT Packages uses: actions/cache@v4 with: path: /var/cache/apt/archives key: apt-cache-${{ runner.os }}-${{ runner.arch }}-chromium - name: 💾 Cache Chromium id: cache-chromium uses: actions/cache@v4 with: path: /usr/bin/chromium key: ${{ runner.os }}-chromium-native-${{ hashFiles('package.json') }} - name: 🔍 Install Chromium (Native & ARM64) if: steps.cache-chromium.outputs.cache-hit != 'true' && steps.deps.outcome == 'success' run: | rm -f /etc/apt/apt.conf.d/docker-clean apt-get update apt-get install -y gnupg wget ca-certificates OS_ID=$(. /etc/os-release && echo $ID) CODENAME=$(. /etc/os-release && echo $VERSION_CODENAME) if [ "$OS_ID" = "debian" ]; then apt-get install -y chromium else mkdir -p /etc/apt/keyrings KEY_ID="82BB6851C64F6880" wget -qO- "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x$KEY_ID" | gpg --dearmor > /etc/apt/keyrings/xtradeb.gpg echo "deb [signed-by=/etc/apt/keyrings/xtradeb.gpg] http://ppa.launchpad.net/xtradeb/apps/ubuntu $CODENAME main" > /etc/apt/sources.list.d/xtradeb-ppa.list printf "Package: *\nPin: release o=LP-PPA-xtradeb-apps\nPin-Priority: 1001\n" > /etc/apt/preferences.d/xtradeb apt-get update apt-get install -y --allow-downgrades chromium fi [ -f /usr/bin/chromium ] && ln -sf /usr/bin/chromium /usr/bin/google-chrome [ -f /usr/bin/chromium ] && ln -sf /usr/bin/chromium /usr/bin/chromium-browser # ── Quality Gates ───────────────────────────────────────────────────────── - name: 🌐 Full Sitemap HTML Validation if: always() && steps.deps.outcome == 'success' env: NEXT_PUBLIC_BASE_URL: ${{ inputs.TARGET_URL }} GATEKEEPER_PASSWORD: ${{ secrets.GATEKEEPER_PASSWORD }} run: pnpm run check:html - name: 🌐 Dynamic Asset Presence & Error Scan if: always() && steps.deps.outcome == 'success' env: NEXT_PUBLIC_BASE_URL: ${{ inputs.TARGET_URL }} GATEKEEPER_PASSWORD: ${{ secrets.GATEKEEPER_PASSWORD }} run: pnpm run check:assets - name: ♿ Accessibility Scan (WCAG) if: always() && steps.deps.outcome == 'success' continue-on-error: true env: NEXT_PUBLIC_BASE_URL: ${{ inputs.TARGET_URL }} GATEKEEPER_PASSWORD: ${{ secrets.GATEKEEPER_PASSWORD }} run: pnpm run check:wcag - name: 📦 Unused Dependencies Scan (depcheck) if: always() && steps.deps.outcome == 'success' continue-on-error: true run: pnpm dlx depcheck --ignores="*eslint*,*typescript*,*tailwindcss*,*postcss*,*prettier*,*@types/*,*husky*,*lint-staged*,*@next/*,*@lhci/*,*commitlint*,*cspell*,*rimraf*,*@payloadcms/*,*start-server-and-test*,*html-validate*,*critters*,*dotenv*,*turbo*" - name: 🔗 Markdown & HTML Link Check (Lychee) if: always() && steps.deps.outcome == 'success' uses: lycheeverse/lychee-action@v2 with: args: --accept 200,204,429 --timeout 15 content/ app/ public/ fail: true - name: 🎭 LHCI Desktop Audit id: lhci_desktop if: always() && steps.deps.outcome == 'success' env: LHCI_URL: ${{ inputs.TARGET_URL }} GATEKEEPER_PASSWORD: ${{ secrets.GATEKEEPER_PASSWORD }} run: pnpm run pagespeed:test -- --collect.settings.preset=desktop - name: 📱 LHCI Mobile Audit id: lhci_mobile if: always() && steps.deps.outcome == 'success' env: LHCI_URL: ${{ inputs.TARGET_URL }} GATEKEEPER_PASSWORD: ${{ secrets.GATEKEEPER_PASSWORD }} run: pnpm run pagespeed:test -- --collect.settings.preset=mobile notifications: name: 🔔 Notify needs: [qa_suite] if: always() runs-on: docker container: image: catthehacker/ubuntu:act-latest steps: - name: 🔔 Gotify shell: bash run: | SUITE="${{ needs.qa_suite.result }}" PROJECT="${{ inputs.PROJECT_NAME }}" URL="${{ inputs.TARGET_URL }}" if [[ "$SUITE" != "success" ]]; then PRIORITY=8 EMOJI="⚠️" STATUS_LINE="Nightly QA Failed! Action required." else PRIORITY=2 EMOJI="✅" STATUS_LINE="Nightly QA Passed perfectly." fi TITLE="$EMOJI $PROJECT Nightly QA" MESSAGE="$STATUS_LINE\n$URL\nPlease check Pipeline output for details." curl -s -k -X POST "${{ secrets.GOTIFY_URL }}/message?token=${{ secrets.GOTIFY_TOKEN }}" \ -F "title=$TITLE" \ -F "message=$MESSAGE" \ -F "priority=$PRIORITY" || true