From ce23b82e0c4830e30736fd6311e3326ec417d56c Mon Sep 17 00:00:00 2001 From: nhthinh-axonivy Date: Fri, 27 Dec 2024 14:01:58 +0700 Subject: [PATCH] feature/IVYPORTAL-17377-Create-pipeline-to-run-Lighthouse-report --- .github/workflows/lighthouse-report.yml | 113 ++++++++---------- .../lighthouse/puppeteer-script.js | 50 ++++++++ 2 files changed, 98 insertions(+), 65 deletions(-) create mode 100644 AxonIvyPortal/portal-selenium-test/lighthouse/puppeteer-script.js diff --git a/.github/workflows/lighthouse-report.yml b/.github/workflows/lighthouse-report.yml index e323d20964..4dee9645bb 100644 --- a/.github/workflows/lighthouse-report.yml +++ b/.github/workflows/lighthouse-report.yml @@ -8,7 +8,7 @@ on: branches: - master -env: # Define reusable environment variables +env: ENGINE_DIR: $GITHUB_WORKSPACE/ivy/engine/nightly ENGINE_URL: https://developer.axonivy.com/permalink/nightly/axonivy-engine.zip WAIT_TIME: 180 @@ -17,9 +17,8 @@ env: # Define reusable environment variables REPORT_DIR: $GITHUB_WORKSPACE/lighthouse-reports jobs: - build: + setup: runs-on: ubuntu-latest - name: Lighthouse Audit steps: - name: Checkout Code uses: actions/checkout@v3 @@ -40,6 +39,7 @@ jobs: echo "export IVY_JAVA_HOME=$JAVA_HOME" >> $GITHUB_ENV echo "export JAVA_HOME=$JAVA_HOME" >> $GITHUB_ENV echo "export PATH=$JAVA_HOME/bin:$PATH" >> $GITHUB_ENV + - name: Set Up and Verify Directories run: | ENGINE_DIR="${GITHUB_WORKSPACE}/ivy/engine/nightly" @@ -47,6 +47,7 @@ jobs: sudo chown -R $USER:$USER $ENGINE_DIR ls -la $ENGINE_DIR echo "ENGINE_DIR=$ENGINE_DIR" >> $GITHUB_ENV + - name: Download Engine run: | cd $ENGINE_DIR @@ -54,6 +55,7 @@ jobs: unzip -o axonivy-engine.zip -d . rm axonivy-engine.zip ls -la + - name: Verify Engine Directory run: | if [ ! -d "$ENGINE_DIR" ]; then @@ -62,19 +64,17 @@ jobs: fi ls -la $ENGINE_DIR ls -la $ENGINE_DIR/bin || true + + build: + runs-on: ubuntu-latest + needs: setup + steps: - name: Start Axon Ivy Engine run: | - # Navigate to engine directory cd "${ENGINE_DIR}/bin" - - # Make engine executable chmod +x ./AxonIvyEngine - - # Start engine in background with logging nohup ./AxonIvyEngine > engine.log 2>&1 & echo $! > engine.pid - - # Wait for engine to start (increased timeout) MAX_ATTEMPTS=180 ATTEMPT=0 echo "Waiting for engine to start..." @@ -96,7 +96,7 @@ jobs: IVY_JAVA_HOME: ${{ env.JAVA_HOME }} JAVA_HOME: ${{ env.JAVA_HOME }} PATH: /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${{ env.JAVA_HOME }}/bin:$PATH - + - name: Build Portal Modules run: | modules=( @@ -114,7 +114,7 @@ jobs: echo "Building $module..." mvn clean install -f $module/pom.xml -Divy.engine.directory=$ENGINE_DIR done - + - name: Deploy Portal Modules run: | DEPLOYMENT=$ENGINE_DIR/system/demo-applications/demo-portal @@ -122,6 +122,7 @@ jobs: cp Showcase/portal-demo-app/target/*.zip $DEPLOYMENT cp Showcase/portal-developer-examples/target/*.iar $DEPLOYMENT cp Showcase/portal-components-examples/target/*.iar $DEPLOYMENT + - name: Wait for Server Health Check run: | echo "Waiting for server to be ready..." @@ -136,15 +137,20 @@ jobs: echo "Server check failed" cat engine.log exit 1 - + + audit: + runs-on: ubuntu-latest + needs: build + steps: - name: Install Chrome Dependencies run: | wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add - sudo sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list' sudo apt-get update sudo apt-get install -y google-chrome-stable xvfb x11-xserver-utils + - name: Install Node.js - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: '18' @@ -153,70 +159,47 @@ jobs: sudo apt-get update sudo apt-get install -y x11-utils npm init -y - npm install lighthouse + npm install lighthouse puppeteer @actions/core + - name: Create Report Directory run: | mkdir -p lighthouse-reports echo "REPORT_DIR=$(pwd)/lighthouse-reports" >> $GITHUB_ENV echo "REPORT_PATH=$(pwd)/lighthouse-reports/report.html" >> $GITHUB_ENV + - name: Set Up Virtual Display run: | - # Start Xvfb with debug output - Xvfb :99 -screen 0 1920x1080x24 -ac & - sleep 3 # Wait for Xvfb to start + Xvfb :99 -screen 0 1920x1080x24 -ac & + sleep 3 export DISPLAY=:99 - xdpyinfo || true # Debug display setup - - name: Run Lighthouse Audit - run: | - mkdir -p ${{ env.REPORT_DIR }} - cd ${{ env.REPORT_DIR }} - - npx lighthouse ${{ env.SERVER_URL }} \ - --chrome-flags="--headless --no-sandbox --disable-gpu" \ - --output=json \ - --output=html \ - --output-path="./report" - - ls -la - env: - DISPLAY: ':99' + xdpyinfo || true + + - name: Run Puppeteer Script + run: node AxonIvyPortal/portal-selenium-test/lighthouse/puppeteer-script.js - - name: Run Lighthouse Audit - run: | - mkdir -p ${{ env.REPORT_DIR }} - cd ${{ env.REPORT_DIR }} - - npx lighthouse ${{ env.SERVER_URL }} \ - --chrome-flags="--headless --no-sandbox --disable-gpu" \ - --output=json \ - --output=html \ - --output-path="./report" - - name: Upload Report id: upload-artifact uses: actions/upload-artifact@v4 with: name: lighthouse-report - path: ${{ env.REPORT_DIR }} + path: lighthouse-report.html - - name: Generate Report Summary + - name: Generate HTML Summary run: | - cd ${{ env.REPORT_DIR }} - - if [ -f "report.report.json" ]; then - { - echo "# šŸš¦ Lighthouse Audit Results" - echo "Generated: $(date)" - echo "" - - echo "## Performance Scores" - jq -r '.categories[] | "### " + (.title) + "\nšŸ“Š Score: " + (.score * 100 | floor | tostring) + "%"' report.report.json - - echo "---" - echo "## Reports" - echo "šŸ“‹ [Download Full Report](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts/${{ steps.upload-artifact.outputs.artifact-id }})" - } >> $GITHUB_STEP_SUMMARY - else - echo "āŒ Report generation failed" >> $GITHUB_STEP_SUMMARY - fi - \ No newline at end of file + node -e " + const core = require('@actions/core'); + const fs = require('fs'); + const path = require('path'); + + const htmlReport = fs.readFileSync('lighthouse-report.html', 'utf8'); + + const summary = core.summary + .addHeading('šŸš¦ Lighthouse Audit Results') + .addRaw(htmlReport) + .addSeparator() + .addLink('šŸ“‹ Download Full Report', + `https://github.com/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}/artifacts/${process.env.ARTIFACT_ID}`) + .write(); + " + env: + ARTIFACT_ID: ${{ steps.upload-artifact.outputs.artifact-id }} \ No newline at end of file diff --git a/AxonIvyPortal/portal-selenium-test/lighthouse/puppeteer-script.js b/AxonIvyPortal/portal-selenium-test/lighthouse/puppeteer-script.js new file mode 100644 index 0000000000..1c2590d0a7 --- /dev/null +++ b/AxonIvyPortal/portal-selenium-test/lighthouse/puppeteer-script.js @@ -0,0 +1,50 @@ +const fs = require("fs"); +const path = require("path"); +const puppeteer = require("puppeteer"); +const lighthouse = require("lighthouse"); +const { URL } = require("url"); +const { exec } = require("child_process"); + +// Read user credentials +const csvFilePath = path.join( + __dirname, + "AxonIvyPortal/portal-selenium-test/jmeter/data/users_local.csv" +); +const users = fs + .readFileSync(csvFilePath, "utf-8") + .split("\n") + .map((line) => { + const [username, password] = line.split(","); + return { username, password }; + }); + +// Puppeteer script to navigate to the dashboard +(async () => { + const browser = await puppeteer.launch({ headless: false }); + const page = await browser.newPage(); + + // Use the first user for login + const user = users[0]; + const loginUrl = "http://localhost:8080/Portal"; // Replace with actual login URL + + await page.goto(loginUrl); + await page.type("#username", user.username); + await page.type("#password", user.password); + await page.click("#login-button"); // Replace with actual login button selector + + // Wait for navigation to dashboard + await page.waitForNavigation(); + + // Run Lighthouse audit + const { lhr } = await lighthouse(page.url(), { + port: new URL(browser.wsEndpoint()).port, + output: "html", + logLevel: "info", + }); + + // Save Lighthouse report + const reportHtml = lhr.report; + fs.writeFileSync("lighthouse-report.html", reportHtml); + + await browser.close(); +})();