From c33d2e60728855e2e240097d1925c043c8da38db Mon Sep 17 00:00:00 2001 From: Anna Finn Date: Tue, 19 Nov 2024 15:04:58 -0500 Subject: [PATCH] dashboard: small enhancements Updated fetch script to require access token, simplified/removed extra PR code, and added error message. Modified basePath, styling change to weatherTemplate/table, added default sort by most Fails. Added win-dev/localData, updated README/.gitignore. Fixes: #25 Signed-off-by: Anna Finn --- .github/workflows/deploy.yml | 10 +- .github/workflows/fetch-ci-nightly-data.yaml | 2 + .gitignore | 7 +- README.md | 29 +- components/weatherTemplate.js | 13 +- next.config.js | 2 +- package-lock.json | 634 ++++++++++++++++--- package.json | 6 +- pages/index.js | 6 +- scripts/fetch-ci-nightly-data.js | 245 ++----- 10 files changed, 665 insertions(+), 289 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f3ba122..e96cb05 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -15,6 +15,9 @@ on: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: +env: + NEXT_PUBLIC_BASE_PATH: ${{ vars.NEXT_PUBLIC_BASE_PATH }} + # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages permissions: contents: read @@ -76,9 +79,14 @@ jobs: - name: Install dependencies run: ${{ steps.detect-package-manager.outputs.manager }} ${{ steps.detect-package-manager.outputs.command }} - - name: Build with Next.js + - name: Build with Next.js (No base path) + if: ${{ env.NEXT_PUBLIC_BASE_PATH == '' }} run: ${{ steps.detect-package-manager.outputs.runner }} next build + - name: Build with Next.js (With base path) + if: ${{ env.NEXT_PUBLIC_BASE_PATH != '' }} + run: NEXT_PUBLIC_BASE_PATH=${{ env.NEXT_PUBLIC_BASE_PATH }} ${{ steps.detect-package-manager.outputs.runner }} next build + - name: Add .nojekyll to out directory run: touch out/.nojekyll diff --git a/.github/workflows/fetch-ci-nightly-data.yaml b/.github/workflows/fetch-ci-nightly-data.yaml index 9e15167..6142a4c 100644 --- a/.github/workflows/fetch-ci-nightly-data.yaml +++ b/.github/workflows/fetch-ci-nightly-data.yaml @@ -19,6 +19,8 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Update dashboard data + env: + TOKEN: ${{ secrets.GITHUB_TOKEN }} # Use bash to fail fast: # https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsshell shell: bash diff --git a/.gitignore b/.gitignore index ce91c51..3546a0b 100644 --- a/.gitignore +++ b/.gitignore @@ -26,8 +26,8 @@ npm-debug.log* yarn-debug.log* yarn-error.log* -# local env files -.env*.local +# env files +.env* # vercel .vercel @@ -36,4 +36,5 @@ yarn-error.log* *.tsbuildinfo next-env.d.ts -/job_stats.json \ No newline at end of file +# local dev data +/localData/ diff --git a/README.md b/README.md index 03c24c6..8e66dd9 100644 --- a/README.md +++ b/README.md @@ -71,11 +71,21 @@ Follow these steps to set up the development environment for the Kata Containers 3. **Run the development server**: Start the Next.js development server with hot-reloading enabled. + + To run the script to fetch the data, a .env file must be created with an access token. This is required to authenticate our calls and increase the rate limit. To get the token, click [here](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens) + + Create the .env file: ```bash - node scripts/fetch-ci-nightly-data.js > job_stats.json - npm run dev + NODE_ENV=development + TOKEN= ``` + Create the folder /localData. Then, run: + + ```bash + node scripts/fetch-ci-nightly-data.js > localData/job_stats.json + npm run dev # On Windows, run `npm run win-dev` instead. + ``` The app will be available at [http://localhost:3000](http://localhost:3000). ### Production @@ -92,10 +102,11 @@ Follow these steps to set up the development environment for the Kata Containers npm start ``` -### Scripts - -- **Fetch CI Nightly Data**: - The `fetch-ci-nightly-data.js` script can be executed manually to pull the latest CI test data from the Kata Containers repository: - ```bash - node scripts/fetch-ci-nightly-data.js > job_stats.json - ``` \ No newline at end of file +### Notes +In deploy.yml: + ```bash +env: + NEXT_PUBLIC_BASE_PATH: ${{ vars.NEXT_PUBLIC_BASE_PATH }} +``` +If the variable is undefined, it will use "" for the basePath and assume the site is being served at root. +This makes it easier for people to fork the repo and deploy with GitHub pages such that they can have a preview for their PR. \ No newline at end of file diff --git a/components/weatherTemplate.js b/components/weatherTemplate.js index 94da4b2..7cdf020 100644 --- a/components/weatherTemplate.js +++ b/components/weatherTemplate.js @@ -11,35 +11,28 @@ const icons = [ export const getWeatherIndex = (stat) => { let fail_rate = 0; - fail_rate = (stat["fails"] + stat["skips"]) / stat["runs"]; + fail_rate = (stat["fails"]) / stat["runs"]; // e.g. failing 3/9 runs is .33, or idx=1 var idx = Math.floor((fail_rate * 10) / 2); if (idx == icons.length) { // edge case: if 100% failures, then we go past the end of icons[] // back the idx down by 1 - console.assert(fail_rate == 1.0); idx -= 1; } // This error checks if there are zero runs. // Currently, will display stormy weather. - if (isNaN(idx)) { + if (isNaN(idx) || idx > icons.length) { idx = 4; } return idx; }; -const getWeatherIcon = (stat) => { - const idx = getWeatherIndex(stat); - return icons[idx]; -}; - export const weatherTemplate = (data) => { - const icon = getWeatherIcon(data); return (
weather=6.9.0" } }, + "node_modules/@emnapi/runtime": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.3.1.tgz", + "integrity": "sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -145,6 +156,367 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.2.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -246,9 +618,9 @@ } }, "node_modules/@next/env": { - "version": "14.2.13", - "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.13.tgz", - "integrity": "sha512-s3lh6K8cbW1h5Nga7NNeXrbe0+2jIIYK9YaA9T7IufDWnZpozdFUp6Hf0d5rNWUKu4fEuSX2rCKlGjCrtylfDw==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.0.3.tgz", + "integrity": "sha512-t9Xy32pjNOvVn2AS+Utt6VmyrshbpfUMhIjFO60gI58deSo/KgLOp31XZ4O+kY/Is8WAGYwA5gR7kOb1eORDBA==", "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { @@ -262,9 +634,9 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "14.2.13", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.13.tgz", - "integrity": "sha512-IkAmQEa2Htq+wHACBxOsslt+jMoV3msvxCn0WFSfJSkv/scy+i/EukBKNad36grRxywaXUYJc9mxEGkeIs8Bzg==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.0.3.tgz", + "integrity": "sha512-s3Q/NOorCsLYdCKvQlWU+a+GeAd3C8Rb3L1YnetsgwXzhc3UTWrtQpB/3eCjFOdGUj5QmXfRak12uocd1ZiiQw==", "cpu": [ "arm64" ], @@ -278,9 +650,9 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "14.2.13", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.13.tgz", - "integrity": "sha512-Dv1RBGs2TTjkwEnFMVL5XIfJEavnLqqwYSD6LXgTPdEy/u6FlSrLBSSfe1pcfqhFEXRAgVL3Wpjibe5wXJzWog==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.0.3.tgz", + "integrity": "sha512-Zxl/TwyXVZPCFSf0u2BNj5sE0F2uR6iSKxWpq4Wlk/Sv9Ob6YCKByQTkV2y6BCic+fkabp9190hyrDdPA/dNrw==", "cpu": [ "x64" ], @@ -294,9 +666,9 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "14.2.13", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.13.tgz", - "integrity": "sha512-yB1tYEFFqo4ZNWkwrJultbsw7NPAAxlPXURXioRl9SdW6aIefOLS+0TEsKrWBtbJ9moTDgU3HRILL6QBQnMevg==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.0.3.tgz", + "integrity": "sha512-T5+gg2EwpsY3OoaLxUIofmMb7ohAUlcNZW0fPQ6YAutaWJaxt1Z1h+8zdl4FRIOr5ABAAhXtBcpkZNwUcKI2fw==", "cpu": [ "arm64" ], @@ -310,9 +682,9 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "14.2.13", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.13.tgz", - "integrity": "sha512-v5jZ/FV/eHGoWhMKYrsAweQ7CWb8xsWGM/8m1mwwZQ/sutJjoFaXchwK4pX8NqwImILEvQmZWyb8pPTcP7htWg==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.0.3.tgz", + "integrity": "sha512-WkAk6R60mwDjH4lG/JBpb2xHl2/0Vj0ZRu1TIzWuOYfQ9tt9NFsIinI1Epma77JVgy81F32X/AeD+B2cBu/YQA==", "cpu": [ "arm64" ], @@ -326,9 +698,9 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "14.2.13", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.13.tgz", - "integrity": "sha512-aVc7m4YL7ViiRv7SOXK3RplXzOEe/qQzRA5R2vpXboHABs3w8vtFslGTz+5tKiQzWUmTmBNVW0UQdhkKRORmGA==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.0.3.tgz", + "integrity": "sha512-gWL/Cta1aPVqIGgDb6nxkqy06DkwJ9gAnKORdHWX1QBbSZZB+biFYPFti8aKIQL7otCE1pjyPaXpFzGeG2OS2w==", "cpu": [ "x64" ], @@ -342,9 +714,9 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "14.2.13", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.13.tgz", - "integrity": "sha512-4wWY7/OsSaJOOKvMsu1Teylku7vKyTuocvDLTZQq0TYv9OjiYYWt63PiE1nTuZnqQ4RPvME7Xai+9enoiN0Wrg==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.0.3.tgz", + "integrity": "sha512-QQEMwFd8r7C0GxQS62Zcdy6GKx999I/rTO2ubdXEe+MlZk9ZiinsrjwoiBL5/57tfyjikgh6GOU2WRQVUej3UA==", "cpu": [ "x64" ], @@ -358,9 +730,9 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "14.2.13", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.13.tgz", - "integrity": "sha512-uP1XkqCqV2NVH9+g2sC7qIw+w2tRbcMiXFEbMihkQ8B1+V6m28sshBwAB0SDmOe0u44ne1vFU66+gx/28RsBVQ==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.0.3.tgz", + "integrity": "sha512-9TEp47AAd/ms9fPNgtgnT7F3M1Hf7koIYYWCMQ9neOwjbVWJsHZxrFbI3iEDJ8rf1TDGpmHbKxXf2IFpAvheIQ==", "cpu": [ "arm64" ], @@ -373,26 +745,10 @@ "node": ">= 10" } }, - "node_modules/@next/swc-win32-ia32-msvc": { - "version": "14.2.13", - "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.13.tgz", - "integrity": "sha512-V26ezyjPqQpDBV4lcWIh8B/QICQ4v+M5Bo9ykLN+sqeKKBxJVDpEc6biDVyluTXTC40f5IqCU0ttth7Es2ZuMw==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">= 10" - } - }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "14.2.13", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.13.tgz", - "integrity": "sha512-WwzOEAFBGhlDHE5Z73mNU8CO8mqMNLqaG+AO9ETmzdCQlJhVtWZnOl2+rqgVQS+YHunjOWptdFmNfbpwcUuEsw==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.0.3.tgz", + "integrity": "sha512-VNAz+HN4OGgvZs6MOoVfnn41kBzT+M+tB+OK4cww6DNyWS6wKaDpaAm/qLeOUbnMh0oVx1+mg0uoYARF69dJyA==", "cpu": [ "x64" ], @@ -485,12 +841,11 @@ "license": "Apache-2.0" }, "node_modules/@swc/helpers": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", - "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.13.tgz", + "integrity": "sha512-UoKGxQ3r5kYI9dALKJapMmuK+1zWM/H17Z1+iwnNmzcJRnfFuevZs375TA5rW31pu4BS4NoSy1fRsexDXfWn5w==", "license": "Apache-2.0", "dependencies": { - "@swc/counter": "^0.1.3", "tslib": "^2.4.0" } }, @@ -1308,11 +1663,25 @@ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "color-name": "~1.1.4" @@ -1325,9 +1694,20 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, + "devOptional": true, "license": "MIT" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "optional": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/commander": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", @@ -1534,6 +1914,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -1571,6 +1961,19 @@ "csstype": "^3.0.2" } }, + "node_modules/dotenv": { + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", @@ -2655,6 +3058,7 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, "license": "ISC" }, "node_modules/graphemer": { @@ -2857,6 +3261,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT", + "optional": true + }, "node_modules/is-async-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", @@ -3579,41 +3990,42 @@ "license": "MIT" }, "node_modules/next": { - "version": "14.2.13", - "resolved": "https://registry.npmjs.org/next/-/next-14.2.13.tgz", - "integrity": "sha512-BseY9YNw8QJSwLYD7hlZzl6QVDoSFHL/URN5K64kVEVpCsSOWeyjbIGK+dZUaRViHTaMQX8aqmnn0PHBbGZezg==", + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/next/-/next-15.0.3.tgz", + "integrity": "sha512-ontCbCRKJUIoivAdGB34yCaOcPgYXr9AAkV/IwqFfWWTXEPUgLYkSkqBhIk9KK7gGmgjc64B+RdoeIDM13Irnw==", "license": "MIT", "dependencies": { - "@next/env": "14.2.13", - "@swc/helpers": "0.5.5", + "@next/env": "15.0.3", + "@swc/counter": "0.1.3", + "@swc/helpers": "0.5.13", "busboy": "1.6.0", "caniuse-lite": "^1.0.30001579", - "graceful-fs": "^4.2.11", "postcss": "8.4.31", - "styled-jsx": "5.1.1" + "styled-jsx": "5.1.6" }, "bin": { "next": "dist/bin/next" }, "engines": { - "node": ">=18.17.0" + "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "14.2.13", - "@next/swc-darwin-x64": "14.2.13", - "@next/swc-linux-arm64-gnu": "14.2.13", - "@next/swc-linux-arm64-musl": "14.2.13", - "@next/swc-linux-x64-gnu": "14.2.13", - "@next/swc-linux-x64-musl": "14.2.13", - "@next/swc-win32-arm64-msvc": "14.2.13", - "@next/swc-win32-ia32-msvc": "14.2.13", - "@next/swc-win32-x64-msvc": "14.2.13" + "@next/swc-darwin-arm64": "15.0.3", + "@next/swc-darwin-x64": "15.0.3", + "@next/swc-linux-arm64-gnu": "15.0.3", + "@next/swc-linux-arm64-musl": "15.0.3", + "@next/swc-linux-x64-gnu": "15.0.3", + "@next/swc-linux-x64-musl": "15.0.3", + "@next/swc-win32-arm64-msvc": "15.0.3", + "@next/swc-win32-x64-msvc": "15.0.3", + "sharp": "^0.33.5" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.41.2", - "react": "^18.2.0", - "react-dom": "^18.2.0", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-66855b96-20241106", + "react-dom": "^18.2.0 || 19.0.0-rc-66855b96-20241106", "sass": "^1.3.0" }, "peerDependenciesMeta": { @@ -3623,6 +4035,9 @@ "@playwright/test": { "optional": true }, + "babel-plugin-react-compiler": { + "optional": true + }, "sass": { "optional": true } @@ -4533,7 +4948,7 @@ "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, + "devOptional": true, "license": "ISC", "bin": { "semver": "bin/semver.js" @@ -4576,6 +4991,46 @@ "node": ">= 0.4" } }, + "node_modules/sharp": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.5", + "@img/sharp-darwin-x64": "0.33.5", + "@img/sharp-libvips-darwin-arm64": "1.0.4", + "@img/sharp-libvips-darwin-x64": "1.0.4", + "@img/sharp-libvips-linux-arm": "1.0.5", + "@img/sharp-libvips-linux-arm64": "1.0.4", + "@img/sharp-libvips-linux-s390x": "1.0.4", + "@img/sharp-libvips-linux-x64": "1.0.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", + "@img/sharp-linux-arm": "0.33.5", + "@img/sharp-linux-arm64": "0.33.5", + "@img/sharp-linux-s390x": "0.33.5", + "@img/sharp-linux-x64": "0.33.5", + "@img/sharp-linuxmusl-arm64": "0.33.5", + "@img/sharp-linuxmusl-x64": "0.33.5", + "@img/sharp-wasm32": "0.33.5", + "@img/sharp-win32-ia32": "0.33.5", + "@img/sharp-win32-x64": "0.33.5" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4631,6 +5086,16 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", + "optional": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -4883,9 +5348,9 @@ } }, "node_modules/styled-jsx": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", - "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", "license": "MIT", "dependencies": { "client-only": "0.0.1" @@ -4894,7 +5359,7 @@ "node": ">= 12.0.0" }, "peerDependencies": { - "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" }, "peerDependenciesMeta": { "@babel/core": { @@ -5079,9 +5544,9 @@ } }, "node_modules/tslib": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", - "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, "node_modules/type-check": { @@ -5508,6 +5973,21 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.13", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.13.tgz", + "integrity": "sha512-V26ezyjPqQpDBV4lcWIh8B/QICQ4v+M5Bo9ykLN+sqeKKBxJVDpEc6biDVyluTXTC40f5IqCU0ttth7Es2ZuMw==", + "cpu": [ + "ia32" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } } } } diff --git a/package.json b/package.json index b1391f9..b54bc49 100644 --- a/package.json +++ b/package.json @@ -3,12 +3,13 @@ "private": true, "scripts": { "dev": "NODE_ENV=development next dev", + "win-dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { - "next": "^14.2.13", + "next": "^15.0.2", "primeflex": "^3.3.1", "primeicons": "^6.0.1", "primereact": "^10.8.3", @@ -18,9 +19,10 @@ }, "devDependencies": { "autoprefixer": "^10.4.20", + "dotenv": "^16.4.5", "eslint": "8.57.0", "eslint-config-next": "^14.2.13", "postcss": "^8.4.47", "tailwindcss": "^3.4.13" } -} +} \ No newline at end of file diff --git a/pages/index.js b/pages/index.js index 087c213..1243636 100644 --- a/pages/index.js +++ b/pages/index.js @@ -16,7 +16,7 @@ export default function Home() { let data = {}; if (process.env.NODE_ENV === "development") { - data = (await import("../job_stats.json")).default; + data = (await import("../localData/job_stats.json")).default; } else { const response = await fetch( "https://raw.githubusercontent.com/kata-containers/kata-containers.github.io" + @@ -130,6 +130,8 @@ export default function Home() { onRowToggle={(e) => setExpandedRows(e.data)} loading={loading} emptyMessage="No results found." + sortField="fails" + sortOrder={-1} > -
{renderTable()}
Total Rows: {rows.length}
+
{renderTable()}
); diff --git a/scripts/fetch-ci-nightly-data.js b/scripts/fetch-ci-nightly-data.js index 804745b..3234fb1 100644 --- a/scripts/fetch-ci-nightly-data.js +++ b/scripts/fetch-ci-nightly-data.js @@ -11,110 +11,91 @@ // entry is information about a job and how it has performed over the last // few runs (e.g. pass or fail). // -// Count of API calls: -// 1 for the batch of last 10 nightly run -// 20 for 2 batches of >100 jobs for each of the 10 runs -// 1 for the main branch details (for list of 'Required' jobs) -// 1 for the last 10 closed pull requests -// 20 for all 4 batches of checks (max of a hundred each) for each of the 5 PRs -// X Other? -// TOTAL: 43? -// LIMIT: 60 per hour // curl https://api.github.com/rate_limit -// TODO: Further explore using the GraphQL API, which permits more narrowly targeted queries - +// To run locally: +// node --require dotenv/config scripts/fetch-ci-nightly-data.js +// +// .env file with: +// NODE_ENV=development +// TOKEN=token + +// Set token used for making Authorized GitHub API calls. +// In dev, set by .env file; in prod, set by GitHub Secret. +require('dotenv').config(); +const TOKEN = process.env.TOKEN; + // Github API URL for the kata-container ci-nightly workflow's runs. This -// will only get the most recent 10 runs ('page' is empty, and 'per_page=10'). +// will only get the most recent 10 runs ('per_page=10'). +const total_runs = 10; + const ci_nightly_runs_url = "https://api.github.com/repos/" + "kata-containers/kata-containers/actions/workflows/" + - "ci-nightly.yaml/runs?per_page=10"; - // NOTE: For checks run on main after push/merge, do similar call with: payload-after-push.yaml - -// NOTE: pull_requests attribute often empty if commit/branch from a fork: https://github.com/orgs/community/discussions/25220 -// Current approach (there may be better alternatives) is to: -// 1. retrieve the last 10 closed PRs -// 2. fetch the checks for each PR (using the head commit SHA) -const pull_requests_url = - "https://api.github.com/repos/" + - "kata-containers/kata-containers/pulls?state=closed&per_page="; -const pr_checks_url = // for our purposes, 'check' refers to a job in the context of a PR - "https://api.github.com/repos/" + - "kata-containers/kata-containers/commits/"; // will be followed by {commit_sha}/check-runs - // Max of 100 per page, w/ little *over* 300 checks total, so that's 40 calls total for 10 PRs + `ci-nightly.yaml/runs?per_page=${total_runs}`; + // NOTE: For checks run on main after push/merge, + // do similar call with: payload-after-push.yaml. // Github API URL for the main branch of the kata-containers repo. // Used to get the list of required jobs. -const main_branch_url = - "https://api.github.com/repos/" + - "kata-containers/kata-containers/branches/main"; +const main_branch_url = "https://api.github.com/repos/" + + "kata-containers/kata-containers/branches/main"; // The number of jobs to fetch from the github API on each paged request. const jobs_per_request = 100; -// The last X closed PRs to retrieve -const pr_count = 5; -// Complete list of jobs (from the CI nightly run) -const job_names = new Set(); -// Count of the number of fetches + +// Count of the number of fetches. let fetch_count = 0; -// Perform a github API request for workflow runs. -async function fetch_workflow_runs() { - fetch_count++; - return fetch(ci_nightly_runs_url, { +// Perform a fetch request (to Github's API). +async function fetch_url(url) { + const response = await fetch(url, { headers: { Accept: "application/vnd.github+json", + Authorization: `token ${TOKEN}`, "X-GitHub-Api-Version": "2022-11-28", }, - }).then(function (response) { - return response.json(); }); -} -// Perform a github API request for the last pr_count closed PRs -async function fetch_pull_requests() { + if (!response.ok) { + throw new Error(`Failed to fetch from ${url}: ${response.status}: ` + + `${response.statusText}`); + } + + const json = await response.json(); fetch_count++; - const prs_url = `${pull_requests_url}${pr_count}`; - return fetch(prs_url, { - headers: { - Accept: "application/vnd.github+json", - "X-GitHub-Api-Version": "2022-11-28", - }, - }).then(function (response) { - return response.json(); - }); + return await json; } -// Perform a github API request for a list of "Required" jobs -async function fetch_main_branch() { - return fetch(main_branch_url, { - headers: { - Accept: "application/vnd.github+json", - "X-GitHub-Api-Version": "2022-11-28", - }, - }).then(function (response) { - return response.json(); - }); +// Extract list of required jobs. +// (i.e. main branch details: protection: required_status_checks: contexts) +function get_required_jobs(main_branch) { + return main_branch["protection"]["required_status_checks"]["contexts"]; } -// Get job data about a workflow run +// Get job data about a workflow run. // Returns a map that has information about a run, e.g. // ID assigned by github // run number assigned by github -// 'jobs' array, which has some details about each job from that run +// 'jobs' array, which has some details about each job from that run. function get_job_data(run) { // Perform the actual (paged) request async function fetch_jobs_by_page(which_page) { - fetch_count++; - const jobs_url = - run["jobs_url"] + "?per_page=" + jobs_per_request + "&page=" + which_page; - return fetch(jobs_url, { + const jobs_url = `${run["jobs_url"]}?per_page=${jobs_per_request}` + + `&page=${which_page}`; + const response = await fetch(jobs_url, { headers: { Accept: "application/vnd.github+json", + Authorization: `token ${TOKEN}`, "X-GitHub-Api-Version": "2022-11-28", }, - }).then(function (response) { - return response.json(); }); + + if (!response.ok) { + throw new Error(`Failed to fetch jobs: ${response.status}: ` + + `${response.statusText}`); + } + const json = await response.json(); + fetch_count++; + return await json; } // Fetch the jobs for a run. Extract a few details from the response, @@ -122,9 +103,6 @@ function get_job_data(run) { function fetch_jobs(p) { return fetch_jobs_by_page(p).then(function (jobs_request) { for (const job of jobs_request["jobs"]) { - if (!job_names.has(job["name"])) { - job_names.add(job["name"]) - }; run_with_job_data["jobs"].push({ name: job["name"], run_id: job["run_id"], @@ -146,7 +124,7 @@ function get_job_data(run) { conclusion: null, jobs: [], }; - if (run["status"] == "in_progress") { + if (run["status"] === "in_progress") { return new Promise((resolve) => { resolve(run_with_job_data); }); @@ -154,70 +132,8 @@ function get_job_data(run) { run_with_job_data["conclusion"] = run["conclusion"]; return fetch_jobs(1); } - -function get_check_data(pr) { - // Perform a github API request for a list of commits for a PR (takes in the PR's head commit SHA) - async function fetch_checks_by_page(which_page) { - fetch_count++; - const checks_url = - pr_checks_url + prs_with_check_data["commit_sha"] + "/check-runs" + "?per_page=" + jobs_per_request + "&page=" + which_page; - return fetch(checks_url, { - headers: { - Accept: "application/vnd.github+json", - "X-GitHub-Api-Version": "2022-11-28", - }, - }).then(function (response) { - return response.json(); - }); - } - - // Fetch the checks for a PR. - function fetch_checks(p) { - if (p > 60) { - throw new Error(`Attempting to make too many API calls: ${p}`) - } - return fetch_checks_by_page(p) - .then(function (checks_request) { - for (const check of checks_request["check_runs"]) { - // NOTE: For now, excluding checks that are not also run in CI Nightly - if (job_names.has(check["name"])) { - prs_with_check_data["checks"].push({ - name: check["name"], - conclusion: check["conclusion"] - }); - } - } - if (p * jobs_per_request >= checks_request["total_count"]) { - return prs_with_check_data; - } - return fetch_checks(p + 1); - }) - .catch(function (error) { - console.error("Error fetching checks:", error); - throw error; - }); - } - - // Extract list of objects with PR commit SHAs, PR URLs, and PR number (i.e. id) - const prs_with_check_data = { - html_url: pr["html_url"], // link to PR page - number: pr["number"], // PR number (used as PR id); displayed on dashboard - commit_sha: pr["head"]["sha"], // For getting checks run on PR branch - // NOTE: using for now b/c we'll be linking to the PR page, where these checks are listed... - checks: [], // will be populated later with fetch_checks - }; - - return fetch_checks(1); -} - -// Extract list of required jobs (i.e. main branch details: protection: required_status_checks: contexts) -function get_required_jobs(main_branch) { - const required_jobs = main_branch["protection"]["required_status_checks"]["contexts"]; - return required_jobs; -} - // Calculate and return job stats across all runs -function compute_job_stats(runs_with_job_data, prs_with_check_data, required_jobs) { +function compute_job_stats(runs_with_job_data, required_jobs) { const job_stats = {}; for (const run of runs_with_job_data) { for (const job of run["jobs"]) { @@ -229,21 +145,14 @@ function compute_job_stats(runs_with_job_data, prs_with_check_data, required_job urls: [], // ordered list of URLs associated w/ each run results: [], // an array of strings, e.g. 'Pass', 'Fail', ... run_nums: [], // ordered list of github-assigned run numbers - - pr_runs: 0, - pr_fails: 0, - pr_skips: 0, - pr_urls: [], // list of PR URLs that this job is associated with - pr_results: [], // list of job statuses for the PRs in which the job was run - pr_nums: [], // list of PR numbers that this job is associated with }; } const job_stat = job_stats[job["name"]]; job_stat["runs"] += 1; job_stat["run_nums"].push(run["run_number"]); job_stat["urls"].push(job["html_url"]); - if (job["conclusion"] != "success") { - if (job["conclusion"] == "skipped") { + if (job["conclusion"] !== "success") { + if (job["conclusion"] === "skipped") { job_stat["skips"] += 1; job_stat["results"].push("Skip"); } else { @@ -257,37 +166,16 @@ function compute_job_stats(runs_with_job_data, prs_with_check_data, required_job job_stat["required"] = required_jobs.includes(job["name"]); } } - for (const pr of prs_with_check_data) { - for (const check of pr["checks"]) { - if ((check["name"] in job_stats)) { - const job_stat = job_stats[check["name"]]; - job_stat["pr_runs"] += 1; - job_stat["pr_urls"].push(pr["html_url"]) - job_stat["pr_nums"].push(pr["number"]) - if (check["conclusion"] != "success") { - if (check["conclusion"] == "skipped") { - job_stat["pr_skips"] += 1; - job_stat["pr_results"].push("Skip"); - } else { - // failed or cancelled - job_stat["pr_fails"] += 1; - job_stat["pr_results"].push("Fail"); - } - } else { - job_stat["pr_results"].push("Pass"); - } - } - } - } return job_stats; } + async function main() { // Fetch recent workflow runs via the github API - const workflow_runs = await fetch_workflow_runs(); + const workflow_runs = await fetch_url(ci_nightly_runs_url); // Fetch required jobs from main branch - const main_branch = await fetch_main_branch(); + const main_branch = await fetch_url(main_branch_url); const required_jobs = get_required_jobs(main_branch); // Fetch job data for each of the runs. @@ -296,23 +184,12 @@ async function main() { for (const run of workflow_runs["workflow_runs"]) { promises_buf.push(get_job_data(run)); } - runs_with_job_data = await Promise.all(promises_buf); - - // Fetch recent pull requests via the github API - const pull_requests = await fetch_pull_requests(); - - // Fetch last pr_count closed PRs - // Store all of this in an array of maps, prs_with_check_data. - const promises_buffer = []; - for (const pr of pull_requests) { - promises_buffer.push(get_check_data(pr)); - } - prs_with_check_data = await Promise.all(promises_buffer); - + let runs_with_job_data = await Promise.all(promises_buf); + // Transform the raw details of each run and its jobs' results into a // an array of just the jobs and their overall results (e.g. pass or fail, // and the URLs associated with them). - const job_stats = compute_job_stats(runs_with_job_data, prs_with_check_data, required_jobs); + const job_stats = compute_job_stats(runs_with_job_data, required_jobs); // Write the job_stats to console as a JSON object console.log(JSON.stringify(job_stats));