From 7c6ca7e84935b5ee83091c4bb3e0e5a5460b0cdb Mon Sep 17 00:00:00 2001 From: bpvstaty366 <148532497+bpvstaty366@users.noreply.github.com> Date: Fri, 8 Mar 2024 17:50:51 +0200 Subject: [PATCH] CoreSDK suite on MFOS - FCA standalone actions (#234) Core sanity suite execution from Mock-Firebolt on the PR --- .github/workflows/pr-comment.yml | 52 ++++++ .../workflows/run-standalone-mfos-tests.yml | 34 ++++ .github/workflows/utils.cjs | 53 ++++++ .github/workflows/utils.sh | 162 ++++++++++++++++++ 4 files changed, 301 insertions(+) create mode 100644 .github/workflows/pr-comment.yml create mode 100644 .github/workflows/run-standalone-mfos-tests.yml create mode 100755 .github/workflows/utils.cjs create mode 100755 .github/workflows/utils.sh diff --git a/.github/workflows/pr-comment.yml b/.github/workflows/pr-comment.yml new file mode 100644 index 000000000..03dd88bc5 --- /dev/null +++ b/.github/workflows/pr-comment.yml @@ -0,0 +1,52 @@ +name: Comment Artifact URL on PR + +on: + workflow_run: + types: + - "completed" + workflows: + - "Core SDK - MFOS standalone sanity report" + +jobs: + comment-on-pr: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Get Artifact And Job Data + env: + GITHUB_TOKEN: ${{ github.token }} + OWNER: ${{ github.repository_owner }} + REPO: ${{ github.event.repository.name }} + SERVER_URL: ${{ github.server_url }} + GITHUB_REPO: ${{ github.repository }} + WORKFLOW_RUN_EVENT_OBJ: ${{ toJSON(github.event.workflow_run) }} + run: | + ./.github/workflows/utils.sh getArtifactData + + - name: Download an artifact + uses: actions/github-script@v6 + with: + script: | + const { downloadArtifact } = require('./.github/workflows/utils.cjs'); + downloadArtifact(process.env.ARTIFACT_ID,process.env.JOB_PATH,process.env.PR_NUMBER,context,github); + + - name: Unzip an artifact + run: | + ./.github/workflows/utils.sh unzipArtifact + + - name: Post a Comment + uses: actions/github-script@v6 + with: + script: | + const { createComment } = require('./.github/workflows/utils.cjs'); + createComment(github, context); + env: + issue_number: ${{ env.PR_NUMBER }} + Passes: ${{ env.Passes }} + Failures: ${{ env.Failures }} + Pending: ${{ env.Pending }} + Skipped: ${{ env.Skipped }} + ARTIFACT_URL: ${{ env.ARTIFACT_URL }} + JOB_PATH: ${{ env.JOB_PATH }} \ No newline at end of file diff --git a/.github/workflows/run-standalone-mfos-tests.yml b/.github/workflows/run-standalone-mfos-tests.yml new file mode 100644 index 000000000..675202521 --- /dev/null +++ b/.github/workflows/run-standalone-mfos-tests.yml @@ -0,0 +1,34 @@ +name: Core SDK - MFOS standalone sanity report + +on: + pull_request: + types: + - opened + - synchronize + branches: [ next ] + +jobs: + RunStandaloneTests: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + + - name: Run tests and create assets + env: + EVENT_NAME: ${{ github.event_name }} + GITHUB_REF: ${{ github.ref }} + PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} + INTENT: ${{ secrets.INTENT }} + run: | + ./.github/workflows/utils.sh runTests + + - name: Upload report.json as an artifact + uses: actions/upload-artifact@v2 + with: + name: report + path: ${{ github.workspace }}/report + + - name: Get results from report.json + run: | + ./.github/workflows/utils.sh getResults \ No newline at end of file diff --git a/.github/workflows/utils.cjs b/.github/workflows/utils.cjs new file mode 100755 index 000000000..32e39a38b --- /dev/null +++ b/.github/workflows/utils.cjs @@ -0,0 +1,53 @@ + +async function downloadArtifact(ARTIFACT_ID, JOB_PATH, PR_NUMBER, context, github) { + if (!ARTIFACT_ID) { + console.log("Send the comment to PR and exit the job"); + // Create a comment + const comment = `Failed to create a report:\n Job logs: ${JOB_PATH}`; + + // Post the comment to the pull request + let prcomment = await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: PR_NUMBER, + body: comment, + }); + + process.exit(1); + } else { + // Download report.json + let download = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: ARTIFACT_ID, + archive_format: 'zip', + }); + + let fs = require('fs'); + fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/report.zip`, Buffer.from(download.data)); + + console.log("Artifact downloaded successfully."); + } +} + +async function createComment(github, context) { + const { issue_number, Passes, Failures, Pending, Skipped, ARTIFACT_URL, JOB_PATH } = process.env; + + const body = ` + Core SDK - MFOS standalone sanity report: + Passes - ${Passes} Failures - ${Failures} Pending - ${Pending} Skipped - ${Skipped} + Report JSON/HTML Files: ${ARTIFACT_URL} + Job Logs: ${JOB_PATH} + `; + + const response = await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue_number, + body: body.trim() + }); + + console.log('Comment updated successfully.'); +} + +module.exports = { downloadArtifact, createComment }; \ No newline at end of file diff --git a/.github/workflows/utils.sh b/.github/workflows/utils.sh new file mode 100755 index 000000000..13c8e7ff7 --- /dev/null +++ b/.github/workflows/utils.sh @@ -0,0 +1,162 @@ +#!/bin/bash +set -o pipefail + +function runTests(){ + echo "Clone firebolt-apis repo with pr branch" + PR_BRANCH=$(echo "$EVENT_NAME" | tr '[:upper:]' '[:lower:]') + if [ "${PR_BRANCH}" == "pull_request" ]; then + PR_BRANCH=$PR_HEAD_REF + elif [ "${PR_BRANCH}" == "push" ]; then + PR_BRANCH=$GITHUB_REF + PR_BRANCH="${PR_BRANCH#refs/heads/}" + else + echo "Unsupported event: $EVENT_NAME" + exit 1 + fi + + git clone --branch ${PR_BRANCH} https://github.com/rdkcentral/firebolt-apis.git + echo "cd to firebolt-apis repo and compile firebolt-open-rpc.json" + cd firebolt-apis + npm i + npm run compile + npm run dist + cd .. + + echo "clone mfos repo and start it in the background" + git clone https://github.com/rdkcentral/mock-firebolt.git + cd mock-firebolt/server + cp ../../firebolt-apis/dist/firebolt-open-rpc.json ../../mock-firebolt/server/src/firebolt-open-rpc.json + jq 'del(.supportedOpenRPCs[] | select(.name == "core"))' src/.mf.config.SAMPLE.json > src/.mf.config.SAMPLE.json.tmp && mv src/.mf.config.SAMPLE.json.tmp src/.mf.config.SAMPLE.json + jq '.supportedOpenRPCs += [{"name": "core","cliFlag": null,"cliShortFlag": null,"fileName": "firebolt-open-rpc.json","enabled": true}]' src/.mf.config.SAMPLE.json > src/.mf.config.SAMPLE.json.tmp && mv src/.mf.config.SAMPLE.json.tmp src/.mf.config.SAMPLE.json + cp src/.mf.config.SAMPLE.json src/.mf.config.json + npm install + npm start & + cd ..//.. + + echo "clone fca repo and start it in the background" + git clone --branch main https://github.com/rdkcentral/firebolt-certification-app.git + cd firebolt-certification-app + jq '.dependencies["@firebolt-js/sdk"] = "file:../firebolt-apis/src/sdks/core"' package.json > package.json.tmp && mv package.json.tmp package.json + npm install + npm start & + sleep 5s + cd .. + + echo "curl request with runTest install on initialization" + response=$(curl -X POST -H "Content-Type: application/json" -d "$INTENT" http://localhost:3333/api/v1/state/method/parameters.initialization/result) + + echo "run mfos tests in a headless browser" + npm install puppeteer + echo "Start xvfb" + Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & + export DISPLAY=:99 + + echo "Run headless browser script with puppeteer" + node -e ' + const puppeteer = require("puppeteer"); + const fs = require("fs"); + (async () => { + const browser = await puppeteer.launch({ headless: true, args: ["--no-sandbox", "--disable-gpu"] }); + const page = await browser.newPage(); + + // Enable console logging + page.on("console", (msg) => { + let logMessage=""; + if (msg.type().includes("log")) { + logMessage = `${msg.text()}`; + console.log(logMessage); + } + if (logMessage.includes("Response String:")) { + const jsonStringMatch = logMessage.match(/Response String:(.*)/); + if (jsonStringMatch && jsonStringMatch[1]) { + try { + const jsonString = jsonStringMatch[1].trim(); + const responseString = JSON.parse(jsonString); + console.log("Parsed JSON:", responseString); + const filePath="report.json" + fs.writeFileSync(filePath, JSON.stringify(responseString), "utf-8"); + console.log(`Parsed JSON written to ${filePath}`); + // Exit the Node.js script + process.exit(0); + + } catch (error) { + console.error("Error parsing JSON:", error); + } + } + } + }); + // Navigate to the URL + await page.goto("http://localhost:8081/?mf=ws://localhost:9998/12345&standalone=true"); + + // Sleep for 80 seconds (80,000 milliseconds) + await new Promise(resolve => setTimeout(resolve, 80000)); + + // Close the browser + await browser.close(); + })(); + ' + echo "create html and json assets" + npm i mochawesome-report-generator + mkdir report + mv report.json report/ + jq -r '.' report/report.json > tmp.json && mv tmp.json report/report.json + jq '.report' report/report.json > tmp.json && mv tmp.json report/report.json + node -e ' + const marge = require("mochawesome-report-generator/bin/cli-main"); + marge({ + _: ["report/report.json"], + reportFileName: "report.json", + reportTitle: "FireboltCertificationTestReport", + reportPageTitle: "FireboltCertificationTestReport", + reportDir: "./report", + }); + ' +} + +function getResults(){ + failures=$(cat report/report.json | jq -r '.stats.failures') + echo "If failures more than 0, fail the job" + echo "Failures=$failures" + if [ "$failures" -eq 0 ]; then + echo "No failures detected." + else + exit 1 + fi +} + +function getArtifactData(){ + PREVIOUS_JOB_ID=$(jq -r '.id' <<< "$WORKFLOW_RUN_EVENT_OBJ") && echo "PREVIOUS_JOB_ID=$PREVIOUS_JOB_ID" >> "$GITHUB_ENV" + SUITE_ID=$(jq -r '.check_suite_id' <<< "$WORKFLOW_RUN_EVENT_OBJ") && echo "SUITE_ID=$SUITE_ID" >> "$GITHUB_ENV" + ARTIFACT_ID=$(gh api "/repos/$OWNER/$REPO/actions/artifacts" --jq ".artifacts[] | select(.workflow_run.id==$PREVIOUS_JOB_ID and .expired==false) | .id") && echo "ARTIFACT_ID=$ARTIFACT_ID" >> "$GITHUB_ENV" + PR_NUMBER=$(jq -r '.pull_requests[0].number' <<< "$WORKFLOW_RUN_EVENT_OBJ") && echo "PR_NUMBER=$PR_NUMBER" >> "$GITHUB_ENV" + ARTIFACT_URL="$SERVER_URL/$GITHUB_REPO/suites/$SUITE_ID/artifacts/$ARTIFACT_ID" && echo "ARTIFACT_URL=$ARTIFACT_URL" >> "$GITHUB_ENV" + JOB_PATH="$SERVER_URL/$GITHUB_REPO/actions/runs/$PREVIOUS_JOB_ID" && echo "JOB_PATH=$JOB_PATH" >> "$GITHUB_ENV" +} + +function unzipArtifact(){ + unzip report.zip + # Extract values from report.json + report=$(cat report.json | jq -r '.') + passes=$(echo "$report" | jq -r '.stats.passes') + failures=$(echo "$report" | jq -r '.stats.failures') + pending=$(echo "$report" | jq -r '.stats.pending') + skipped=$(echo "$report" | jq -r '.stats.skipped') + echo "Skipped=$skipped" >> "$GITHUB_ENV" + echo "Pending=$pending" >> "$GITHUB_ENV" + echo "Passes=$passes" >> "$GITHUB_ENV" + echo "Failures=$failures" >> "$GITHUB_ENV" +} + +# Check argument and call corresponding function +if [ "$1" == "runTests" ]; then + runTests +elif [ "$1" == "getResults" ]; then + getResults +elif [ "$1" == "getArtifactData" ]; then + getArtifactData +elif [ "$1" == "unzipArtifact" ]; then + unzipArtifact +else + echo "Invalid function specified." + exit 1 +fi \ No newline at end of file