From 0ef2e830578629966bd282187907d0095bba04f4 Mon Sep 17 00:00:00 2001 From: Marcin Czerniak Date: Wed, 29 Mar 2023 12:57:38 +0200 Subject: [PATCH 1/4] feature/codecov --- .../actions/cache-target-outputs/action.yml | 24 ++ .github/actions/cache-target-outputs/index.js | 52 ++++ .github/workflows/_publish-code-coverage.yml | 37 +++ .github/workflows/_test.yml | 8 +- .github/workflows/dev-push.yml | 7 +- README.md | 5 +- package.json | 3 +- packages/client/package.json | 24 ++ packages/client/tools/badge-generator.js | 2 +- packages/tools/list-lcov-files.js | 34 +++ packages/tools/utils/nx-affected.js | 25 ++ yarn.lock | 260 +++++++++++++++++- 12 files changed, 468 insertions(+), 13 deletions(-) create mode 100644 .github/actions/cache-target-outputs/action.yml create mode 100644 .github/actions/cache-target-outputs/index.js create mode 100644 .github/workflows/_publish-code-coverage.yml create mode 100644 packages/tools/list-lcov-files.js create mode 100644 packages/tools/utils/nx-affected.js diff --git a/.github/actions/cache-target-outputs/action.yml b/.github/actions/cache-target-outputs/action.yml new file mode 100644 index 00000000..8f551cc8 --- /dev/null +++ b/.github/actions/cache-target-outputs/action.yml @@ -0,0 +1,24 @@ +# Save cache for specific nx target outputs + +name: Save cache +description: Save cache for single directory + +inputs: + configuration: + description: The configuration to use (development | insiders | production) + required: true + default: development + + target: + description: The target to use (build | test) + required: true + default: build + + os: + description: The operating system of the runner + required: true + default: ${{ runner.os }} + +runs: + using: 'node16' + main: 'index.js' \ No newline at end of file diff --git a/.github/actions/cache-target-outputs/index.js b/.github/actions/cache-target-outputs/index.js new file mode 100644 index 00000000..a61e6dea --- /dev/null +++ b/.github/actions/cache-target-outputs/index.js @@ -0,0 +1,52 @@ +const cache = require('@actions/cache'); +const core = require('@actions/core'); +const { nxAffected } = require('../../../packages/tools/utils/nx-affected'); +const { readFileSync, existsSync } = require('fs'); +const { resolve } = require('path'); + +/** + * @param {string} project + * @returns {Promise<{ + * targets?: { [key: string]: { + * outputs?: string[] + * } } + * }>} + */ +async function getProjectNxConfig(project) { + const packageJSONPath = resolve(__dirname, `../../../packages/${project}/package.json`); + const projectJSONPath = resolve(__dirname, `../../../packages/${project}/project.json`); + + if (!existsSync(packageJSONPath) && !existsSync(projectJSONPath)) { + throw new Error(`Project config not found. One of the following should exist:\n ${packageJSONPath}\n ${projectJSONPath}\n`) + } + + if (existsSync(packageJSONPath)) { + return JSON.parse(readFileSync(packageJSONPath)).nx; + } else { + return JSON.parse(readFileSync(projectJSONPath)); + } +} + +async function run() { + const configuration = core.getInput('configuration'); + const target = core.getInput('target'); + const os = core.getInput('os'); + + const affected = await nxAffected(target); + + for (const project of affected.projects) { + const key = `${os}-${configuration}-${target}-${project}`; + const nxConfig = await getProjectNxConfig(project); + const paths = nxConfig.targets?.[target]?.outputs || []; + + if (paths.length) { + await cache.saveCache(paths, key); + console.log('Successfully cached paths:'); + console.log(paths.join('\n')); + } else { + console.log('No outputs to cache'); + } + } +} + +run(); diff --git a/.github/workflows/_publish-code-coverage.yml b/.github/workflows/_publish-code-coverage.yml new file mode 100644 index 00000000..cd6cb82a --- /dev/null +++ b/.github/workflows/_publish-code-coverage.yml @@ -0,0 +1,37 @@ +name: Code Coverage + +on: + workflow_call: + secrets: + CODECOV_TOKEN: + required: true + description: codecov token for authorization + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: '16.x' + + - name: Restore cache for target test + uses: ./.github/actions/restore-target-outputs + with: + target: test + configuration: development + + - name: List all test files + id: list_lcov_files + run: echo "LCOV_FILES=$(node packages/tools/list-lcov-files.js)" >> $GITHUB_OUTPUT + + - name: Upload app coverage to Codecov + uses: codecov/codecov-action@v2 + with: + files: ${{ steps.list_lcov_files.outputs.LCOV_FILES }} + token: ${{ secrets.CODECOV_TOKEN }} diff --git a/.github/workflows/_test.yml b/.github/workflows/_test.yml index b4703cba..84791322 100644 --- a/.github/workflows/_test.yml +++ b/.github/workflows/_test.yml @@ -39,6 +39,12 @@ jobs: spring-application-properties: ${{ secrets.SPRING_APPLICATION_PROPERTIES }} vernite-2022-private-key-pem: ${{ secrets.VERNITE_2022_PRIVATE_KEY_PEM }} - # Test by nx - name: Test run: yarn nx affected --target=test + + - name: Cache results of affected projects + uses: ./.github/actions/cache-target-outputs + with: + target: test + configuration: ${{ inputs.configuration }} + diff --git a/.github/workflows/dev-push.yml b/.github/workflows/dev-push.yml index 6ed6acb7..9011040c 100644 --- a/.github/workflows/dev-push.yml +++ b/.github/workflows/dev-push.yml @@ -35,7 +35,7 @@ jobs: configuration: insiders sonar_server: - needs: [build] + needs: [build, test] uses: ./.github/workflows/_server-sonar.yml secrets: inherit with: @@ -47,3 +47,8 @@ jobs: secrets: inherit with: configuration: insiders + + publish_code_coverage: + needs: [build, test] + uses: ./.github/workflows/_publish-code-coverage.yml + secrets: inherit diff --git a/README.md b/README.md index d5b98e9f..5ef122b5 100644 --- a/README.md +++ b/README.md @@ -28,9 +28,10 @@ Before starting make sure you have installed the supported version of node and yarn. -- yarn: `1.22.18` - node: `16.13.0` -- java: `17` +- yarn: `1.22.18` +- java: `17.0.6` +- mvn: `3.9.1` This repository is using nx workspace. To install all dependencies run: diff --git a/package.json b/package.json index efe26926..f848cf8c 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "private": true, "prettier": "./.config/.prettierrc.js", "dependencies": { + "@actions/cache": "^3.1.4", "@angular/animations": "^14.2.12", "@angular/cdk": "^14.2.7", "@angular/cdk-experimental": "14.2.7", @@ -129,4 +130,4 @@ "packages/*" ] } -} \ No newline at end of file +} diff --git a/packages/client/package.json b/packages/client/package.json index b984b3c7..ee3b18d4 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -59,9 +59,33 @@ "nx": { "targets": { "build": { + "inputs": [ + "../../tsconfig.json", + "src/", + "angular.json", + "package.json", + "tailwind.config.js", + "tsconfig.app.json", + "tsconfig.json" + ], "outputs": [ "dist/" ] + }, + "test": { + "inputs": [ + "../../tsconfig.json", + "src/", + "angular.json", + "karma.conf.js", + "package.json", + "tailwind.config.js", + "tsconfig.json", + "tsconfig.spec.json" + ], + "outputs": [ + "coverage/" + ] } } } diff --git a/packages/client/tools/badge-generator.js b/packages/client/tools/badge-generator.js index d6b239cf..d5516bc5 100644 --- a/packages/client/tools/badge-generator.js +++ b/packages/client/tools/badge-generator.js @@ -7,7 +7,7 @@ function requireIfExists(...modules) { // pass and try next file } } - throw ('None of the provided modules exist.') + throw new Error('None of the provided modules exist.') } let { makeBadge } = require('badge-maker'); diff --git a/packages/tools/list-lcov-files.js b/packages/tools/list-lcov-files.js new file mode 100644 index 00000000..39899099 --- /dev/null +++ b/packages/tools/list-lcov-files.js @@ -0,0 +1,34 @@ +import { readdir } from 'fs/promises'; +import { lstatSync } from 'fs'; +import path from 'path'; + +const findFiles = async (dir, fileName, options) => { + dir = path.resolve(process.cwd(), dir); + + const directoriesToOmit = options?.omit || []; + let matchedFiles = []; + + const files = await readdir(dir); + + for (const file of files) { + const pathToFile = path.resolve(dir, file); + + if (directoriesToOmit.includes(file)) continue; + + if (lstatSync(pathToFile).isDirectory()) { + matchedFiles = [].concat(matchedFiles, await findFiles(pathToFile, fileName, options)) + } else { + if (file == fileName) { + matchedFiles.push(pathToFile); + } + } + } + + return matchedFiles; +}; + +const files = await findFiles('.', 'lcov.info', { + omit: ['node_modules', 'maven_repository'] +}); + +console.log(JSON.stringify(files)) diff --git a/packages/tools/utils/nx-affected.js b/packages/tools/utils/nx-affected.js new file mode 100644 index 00000000..41b7ad8e --- /dev/null +++ b/packages/tools/utils/nx-affected.js @@ -0,0 +1,25 @@ +import { exec } from 'child_process'; + +/** + * @param {*} target + * @returns {Promise<{ projects: string[] }>} + */ +export function nxAffected(target) { + let command = `nx print-affected`; + + if (target) { + command += ` --target=${target}`; + } + + return new Promise((resolve, reject) => { + exec(command, (error, stdout, stderr) => { + if (error) { + reject(error); + } + if (stderr) { + reject(stderr); + } + resolve(stdout); + }); + }); +} \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index cb46d5f6..516b5c9a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,57 @@ # yarn lockfile v1 +"@actions/cache@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@actions/cache/-/cache-3.1.4.tgz#409a2befcc7ed66633a194afbd30ab9360b7880a" + integrity sha512-Uh9wsz7SxunfyqF3UY/wfHI81z97CYQrZs4NU+whzYd0N8emTaloB+XtrAq46X2RbQEOBjF6R090jKQpX4coGg== + dependencies: + "@actions/core" "^1.10.0" + "@actions/exec" "^1.0.1" + "@actions/glob" "^0.1.0" + "@actions/http-client" "^2.0.1" + "@actions/io" "^1.0.1" + "@azure/abort-controller" "^1.1.0" + "@azure/ms-rest-js" "^2.6.0" + "@azure/storage-blob" "^12.8.0" + semver "^6.1.0" + uuid "^3.3.3" + +"@actions/core@^1.10.0", "@actions/core@^1.2.6": + version "1.10.0" + resolved "https://registry.yarnpkg.com/@actions/core/-/core-1.10.0.tgz#44551c3c71163949a2f06e94d9ca2157a0cfac4f" + integrity sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug== + dependencies: + "@actions/http-client" "^2.0.1" + uuid "^8.3.2" + +"@actions/exec@^1.0.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@actions/exec/-/exec-1.1.1.tgz#2e43f28c54022537172819a7cf886c844221a611" + integrity sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w== + dependencies: + "@actions/io" "^1.0.1" + +"@actions/glob@^0.1.0": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@actions/glob/-/glob-0.1.2.tgz#9685ed2d6583093479c8f137d067c4329d7d0974" + integrity sha512-SclLR7Ia5sEqjkJTPs7Sd86maMDw43p769YxBOxvPvEWuPEhpAnBsQfENOpXjFYMmhCqd127bmf+YdvJqVqR4A== + dependencies: + "@actions/core" "^1.2.6" + minimatch "^3.0.4" + +"@actions/http-client@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@actions/http-client/-/http-client-2.0.1.tgz#873f4ca98fe32f6839462a6f046332677322f99c" + integrity sha512-PIXiMVtz6VvyaRsGY268qvj57hXQEpsYogYOu2nrQhlf+XCGmZstmuZBbAybUl1nQGnvS1k1eEsQ69ZoD7xlSw== + dependencies: + tunnel "^0.0.6" + +"@actions/io@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@actions/io/-/io-1.1.2.tgz#766ac09674a289ce0f1550ffe0a6eac9261a8ea9" + integrity sha512-d+RwPlMp+2qmBfeLYPLXuSRykDIFEwdTA0MMxzS9kh4kvP1ftrc/9fzy6pX6qAjthdXruHQ6/6kjT/DNo5ALuw== + "@adobe/css-tools@^4.0.1": version "4.1.0" resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.1.0.tgz#417fef4a143f4396ad0b3b4351fee21323f15aa8" @@ -371,6 +422,109 @@ resolved "https://registry.yarnpkg.com/@assemblyscript/loader/-/loader-0.10.1.tgz#70e45678f06c72fa2e350e8553ec4a4d72b92e06" integrity sha512-H71nDOOL8Y7kWRLqf6Sums+01Q5msqBW2KhDUTemh1tvY04eSkSXrK0uj/4mmY0Xr16/3zyZmsrxN7CKuRbNRg== +"@azure/abort-controller@^1.0.0", "@azure/abort-controller@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@azure/abort-controller/-/abort-controller-1.1.0.tgz#788ee78457a55af8a1ad342acb182383d2119249" + integrity sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw== + dependencies: + tslib "^2.2.0" + +"@azure/core-auth@^1.1.4", "@azure/core-auth@^1.3.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.4.0.tgz#6fa9661c1705857820dbc216df5ba5665ac36a9e" + integrity sha512-HFrcTgmuSuukRf/EdPmqBrc5l6Q5Uu+2TbuhaKbgaCpP2TfAeiNaQPAadxO+CYBRHGUzIDteMAjFspFLDLnKVQ== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + +"@azure/core-http@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@azure/core-http/-/core-http-3.0.0.tgz#345845f9ba479a5ee41efc3fd7a13e82d2a0ec47" + integrity sha512-BxI2SlGFPPz6J1XyZNIVUf0QZLBKFX+ViFjKOkzqD18J1zOINIQ8JSBKKr+i+v8+MB6LacL6Nn/sP/TE13+s2Q== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-auth" "^1.3.0" + "@azure/core-tracing" "1.0.0-preview.13" + "@azure/core-util" "^1.1.1" + "@azure/logger" "^1.0.0" + "@types/node-fetch" "^2.5.0" + "@types/tunnel" "^0.0.3" + form-data "^4.0.0" + node-fetch "^2.6.7" + process "^0.11.10" + tslib "^2.2.0" + tunnel "^0.0.6" + uuid "^8.3.0" + xml2js "^0.4.19" + +"@azure/core-lro@^2.2.0": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@azure/core-lro/-/core-lro-2.5.1.tgz#9c6be24b84f8a8c8e8ac376c5018460c5a585d0b" + integrity sha512-JHQy/bA3NOz2WuzOi5zEk6n/TJdAropupxUT521JIJvW7EXV2YN2SFYZrf/2RHeD28QAClGdynYadZsbmP+nyQ== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/logger" "^1.0.0" + tslib "^2.2.0" + +"@azure/core-paging@^1.1.1": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@azure/core-paging/-/core-paging-1.5.0.tgz#5a5b09353e636072e6a7fc38f7879e11d0afb15f" + integrity sha512-zqWdVIt+2Z+3wqxEOGzR5hXFZ8MGKK52x4vFLw8n58pR6ZfKRx3EXYTxTaYxYHc/PexPUTyimcTWFJbji9Z6Iw== + dependencies: + tslib "^2.2.0" + +"@azure/core-tracing@1.0.0-preview.13": + version "1.0.0-preview.13" + resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.0-preview.13.tgz#55883d40ae2042f6f1e12b17dd0c0d34c536d644" + integrity sha512-KxDlhXyMlh2Jhj2ykX6vNEU0Vou4nHr025KoSEiz7cS3BNiHNaZcdECk/DmLkEB0as5T7b/TpRcehJ5yV6NeXQ== + dependencies: + "@opentelemetry/api" "^1.0.1" + tslib "^2.2.0" + +"@azure/core-util@^1.1.1": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.2.0.tgz#3499deba1fc36dda6f1912b791809b6f15d4a392" + integrity sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng== + dependencies: + "@azure/abort-controller" "^1.0.0" + tslib "^2.2.0" + +"@azure/logger@^1.0.0": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.4.tgz#28bc6d0e5b3c38ef29296b32d35da4e483593fa1" + integrity sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg== + dependencies: + tslib "^2.2.0" + +"@azure/ms-rest-js@^2.6.0": + version "2.6.4" + resolved "https://registry.yarnpkg.com/@azure/ms-rest-js/-/ms-rest-js-2.6.4.tgz#b0a0f89841434471adf757d09e7e39e8ecfcd650" + integrity sha512-2sbOpGhlBfv9itWdF7Qlk0CmoQCARxe5unwjNOprU7OdgEgabQncZ35L5u1A+zgdkVtNYF9Eo6XAhXzTweIhag== + dependencies: + "@azure/core-auth" "^1.1.4" + abort-controller "^3.0.0" + form-data "^2.5.0" + node-fetch "^2.6.7" + tough-cookie "^3.0.1" + tslib "^1.10.0" + tunnel "0.0.6" + uuid "^8.3.2" + xml2js "^0.4.19" + +"@azure/storage-blob@^12.8.0": + version "12.13.0" + resolved "https://registry.yarnpkg.com/@azure/storage-blob/-/storage-blob-12.13.0.tgz#9209cbb5c2cd463fb967a0f2ae144ace20879160" + integrity sha512-t3Q2lvBMJucgTjQcP5+hvEJMAsJSk0qmAnjDLie2td017IiduZbbC9BOcFfmwzR6y6cJdZOuewLCNFmEx9IrXA== + dependencies: + "@azure/abort-controller" "^1.0.0" + "@azure/core-http" "^3.0.0" + "@azure/core-lro" "^2.2.0" + "@azure/core-paging" "^1.1.1" + "@azure/core-tracing" "1.0.0-preview.13" + "@azure/logger" "^1.0.0" + events "^3.0.0" + tslib "^2.2.0" + "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" @@ -2358,6 +2512,11 @@ resolved "https://registry.yarnpkg.com/@oozcitak/util/-/util-8.3.8.tgz#10f65fe1891fd8cde4957360835e78fd1936bfdd" integrity sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ== +"@opentelemetry/api@^1.0.1": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.4.0.tgz#2c91791a9ba6ca0a0f4aaac5e45d58df13639ac8" + integrity sha512-IgMK9i3sFGNUqPMbjABm0G26g0QCKCUBfglhQ7rQq6WcxbKfEHRcmwsoER4hZcuYqJgkYn2OeuoJIv7Jsftp7g== + "@parcel/watcher@2.0.4": version "2.0.4" resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.0.4.tgz#f300fef4cc38008ff4b8c29d92588eced3ce014b" @@ -2888,6 +3047,14 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.1.tgz#2f4f65bb08bc368ac39c96da7b2f09140b26851b" integrity sha512-/fvYntiO1GeICvqbQ3doGDIP97vWmvFt83GKguJ6prmQM2iXZfFcq6YE8KteFyRtX2/h5Hf91BYvPodJKFYv5Q== +"@types/node-fetch@^2.5.0": + version "2.6.2" + resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.2.tgz#d1a9c5fd049d9415dce61571557104dec3ec81da" + integrity sha512-DHqhlq5jeESLy19TYhLakJ07kNumXWjcDdxXsLUMJZ6ue8VZJj4kLPQVE/2mdHh3xZziNF1xppu5lwmS53HR+A== + dependencies: + "@types/node" "*" + form-data "^3.0.0" + "@types/node@*", "@types/node@>=10.0.0", "@types/node@>=13.7.0": version "18.11.18" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.18.tgz#8dfb97f0da23c2293e554c5a50d61ef134d7697f" @@ -2970,6 +3137,13 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== +"@types/tunnel@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@types/tunnel/-/tunnel-0.0.3.tgz#f109e730b072b3136347561fc558c9358bb8c6e9" + integrity sha512-sOUTGn6h1SfQ+gbgqC364jLFBw2lnFqkgF3q0WovEHRLMrVD1sd5aufqi/aJObLekJO+Aq5z646U4Oxy6shXMA== + dependencies: + "@types/node" "*" + "@types/ua-parser-js@^0.7.36": version "0.7.36" resolved "https://registry.yarnpkg.com/@types/ua-parser-js/-/ua-parser-js-0.7.36.tgz#9bd0b47f26b5a3151be21ba4ce9f5fa457c5f190" @@ -3401,6 +3575,13 @@ abbrev@^1.0.0: resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== +abort-controller@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392" + integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg== + dependencies: + event-target-shim "^5.0.0" + accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.8: version "1.3.8" resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e" @@ -4501,7 +4682,7 @@ colors@1.4.0: resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== -combined-stream@^1.0.8: +combined-stream@^1.0.6, combined-stream@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== @@ -5787,6 +5968,11 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== +event-target-shim@^5.0.0: + version "5.0.1" + resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789" + integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ== + eventemitter-asyncresource@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eventemitter-asyncresource/-/eventemitter-asyncresource-1.0.0.tgz#734ff2e44bf448e627f7748f905d6bdd57bdb65b" @@ -5797,7 +5983,7 @@ eventemitter3@^4.0.0: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -events@^3.2.0: +events@^3.0.0, events@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== @@ -6126,6 +6312,24 @@ fork-ts-checker-webpack-plugin@7.2.13: semver "^7.3.5" tapable "^2.2.1" +form-data@^2.5.0: + version "2.5.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.1.tgz#f2cbec57b5e59e23716e128fe44d4e5dd23895f4" + integrity sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +form-data@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" + integrity sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + form-data@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" @@ -6906,6 +7110,11 @@ internal-slot@^1.0.4: has "^1.0.3" side-channel "^1.0.4" +ip-regex@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" + integrity sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw== + ip@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" @@ -8604,7 +8813,7 @@ node-domexception@^1.0.0: resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ== -node-fetch@^2.6.1: +node-fetch@^2.6.1, node-fetch@^2.6.7: version "2.6.9" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.9.tgz#7c7f744b5cc6eb5fd404e0c7a9fec630a55657e6" integrity sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg== @@ -9992,7 +10201,12 @@ pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== -punycode@^2.1.0: +psl@^1.1.28: + version "1.9.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" + integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + +punycode@^2.1.0, punycode@^2.1.1: version "2.3.0" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== @@ -10434,7 +10648,7 @@ sass@^1.42.1: immutable "^4.0.0" source-map-js ">=0.6.2 <2.0.0" -sax@^1.2.4, sax@~1.2.4: +sax@>=0.6.0, sax@^1.2.4, sax@~1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -10510,7 +10724,7 @@ semver@7.3.8, semver@^7.0.0, semver@^7.1.1, semver@^7.3.4, semver@^7.3.5, semver dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: +semver@^6.0.0, semver@^6.1.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: version "6.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== @@ -11461,6 +11675,15 @@ totalist@^1.0.0: resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== +tough-cookie@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-3.0.1.tgz#9df4f57e739c26930a018184887f4adb7dca73b2" + integrity sha512-yQyJ0u4pZsv9D4clxO69OEjLWYw+jbgspjTue4lTQZLfV0c5l1VmK2y1JK8E9ahdpltPOaAThPcp5nKPUgSnsg== + dependencies: + ip-regex "^2.1.0" + psl "^1.1.28" + punycode "^2.1.1" + tr46@~0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" @@ -11600,6 +11823,11 @@ tsutils@^3.21.0: dependencies: tslib "^1.8.1" +tunnel@0.0.6, tunnel@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" + integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== + type-check@^0.4.0, type-check@~0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" @@ -11815,7 +12043,12 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== -uuid@^8.3.2: +uuid@^3.3.3: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +uuid@^8.3.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -12278,6 +12511,14 @@ ws@~8.2.3: resolved "https://registry.yarnpkg.com/ws/-/ws-8.2.3.tgz#63a56456db1b04367d0b721a0b80cae6d8becbba" integrity sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA== +xml2js@^0.4.19: + version "0.4.23" + resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.23.tgz#a0c69516752421eb2ac758ee4d4ccf58843eac66" + integrity sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug== + dependencies: + sax ">=0.6.0" + xmlbuilder "~11.0.0" + xmlbuilder2@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/xmlbuilder2/-/xmlbuilder2-3.0.2.tgz#fc499688b35a916f269e7b459c2fa02bb5c0822a" @@ -12289,6 +12530,11 @@ xmlbuilder2@3.0.2: "@types/node" "*" js-yaml "3.14.0" +xmlbuilder@~11.0.0: + version "11.0.1" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3" + integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA== + xpath@0.0.32: version "0.0.32" resolved "https://registry.yarnpkg.com/xpath/-/xpath-0.0.32.tgz#1b73d3351af736e17ec078d6da4b8175405c48af" From bced504a0c75becbe232833c85f2c0bee0b32865 Mon Sep 17 00:00:00 2001 From: Marcin Czerniak Date: Wed, 29 Mar 2023 16:34:58 +0200 Subject: [PATCH 2/4] Add restore cache action --- .../actions/cache-target-outputs/action.yml | 8 +-- .github/actions/cache-target-outputs/index.js | 15 ++++- .../actions/restore-target-outputs/action.yml | 24 +++++++ .../actions/restore-target-outputs/index.js | 65 +++++++++++++++++++ packages/client/package.json | 34 +++++----- 5 files changed, 124 insertions(+), 22 deletions(-) create mode 100644 .github/actions/restore-target-outputs/action.yml create mode 100644 .github/actions/restore-target-outputs/index.js diff --git a/.github/actions/cache-target-outputs/action.yml b/.github/actions/cache-target-outputs/action.yml index 8f551cc8..0f4ced57 100644 --- a/.github/actions/cache-target-outputs/action.yml +++ b/.github/actions/cache-target-outputs/action.yml @@ -1,7 +1,7 @@ # Save cache for specific nx target outputs name: Save cache -description: Save cache for single directory +description: Save cache for all affected projects inputs: configuration: @@ -13,12 +13,12 @@ inputs: description: The target to use (build | test) required: true default: build - + os: - description: The operating system of the runner + description: The operating system of the runner required: true default: ${{ runner.os }} runs: using: 'node16' - main: 'index.js' \ No newline at end of file + main: 'index.js' diff --git a/.github/actions/cache-target-outputs/index.js b/.github/actions/cache-target-outputs/index.js index a61e6dea..7c9059e4 100644 --- a/.github/actions/cache-target-outputs/index.js +++ b/.github/actions/cache-target-outputs/index.js @@ -27,6 +27,16 @@ async function getProjectNxConfig(project) { } } +function parsePath(path, project) { + const projectRoot = resolve(__dirname, `../../../packages/${project}/`); + const workspaceRoot = resolve(__dirname, '../../'); + + path = path.replace('{projectRoot}', projectRoot); + path = path.replace('{workspaceRoot}', workspaceRoot); + + return path; +} + async function run() { const configuration = core.getInput('configuration'); const target = core.getInput('target'); @@ -37,10 +47,13 @@ async function run() { for (const project of affected.projects) { const key = `${os}-${configuration}-${target}-${project}`; const nxConfig = await getProjectNxConfig(project); - const paths = nxConfig.targets?.[target]?.outputs || []; + const paths = (nxConfig.targets?.[target]?.outputs || []).map((path) => { + return parsePath(path, project); + }); if (paths.length) { await cache.saveCache(paths, key); + console.log('Successfully cached paths:'); console.log(paths.join('\n')); } else { diff --git a/.github/actions/restore-target-outputs/action.yml b/.github/actions/restore-target-outputs/action.yml new file mode 100644 index 00000000..696f7359 --- /dev/null +++ b/.github/actions/restore-target-outputs/action.yml @@ -0,0 +1,24 @@ +# Restore cache for specific nx target outputs + +name: Restore cache +description: Restore cache for all projects + +inputs: + configuration: + description: The configuration to use (development | insiders | production) + required: true + default: development + + target: + description: The target to use (build | test) + required: true + default: build + + os: + description: The operating system of the runner + required: true + default: ${{ runner.os }} + +runs: + using: 'node16' + main: 'index.js' diff --git a/.github/actions/restore-target-outputs/index.js b/.github/actions/restore-target-outputs/index.js new file mode 100644 index 00000000..c3f65ac3 --- /dev/null +++ b/.github/actions/restore-target-outputs/index.js @@ -0,0 +1,65 @@ +const cache = require('@actions/cache'); +const core = require('@actions/core'); +const { nxAffected } = require('../../../packages/tools/utils/nx-affected'); +const { readFileSync, existsSync } = require('fs'); +const { resolve } = require('path'); + +/** + * @param {string} project + * @returns {Promise<{ + * targets?: { [key: string]: { + * outputs?: string[] + * } } + * }>} + */ +async function getProjectNxConfig(project) { + const packageJSONPath = resolve(__dirname, `../../../packages/${project}/package.json`); + const projectJSONPath = resolve(__dirname, `../../../packages/${project}/project.json`); + + if (!existsSync(packageJSONPath) && !existsSync(projectJSONPath)) { + throw new Error(`Project config not found. One of the following should exist:\n ${packageJSONPath}\n ${projectJSONPath}\n`) + } + + if (existsSync(packageJSONPath)) { + return JSON.parse(readFileSync(packageJSONPath)).nx; + } else { + return JSON.parse(readFileSync(projectJSONPath)); + } +} + +function parsePath(path, project) { + const projectRoot = resolve(__dirname, `../../../packages/${project}/`); + const workspaceRoot = resolve(__dirname, '../../'); + + path = path.replace('{projectRoot}', projectRoot); + path = path.replace('{workspaceRoot}', workspaceRoot); + + return path; +} + +async function run() { + const configuration = core.getInput('configuration'); + const target = core.getInput('target'); + const os = core.getInput('os'); + + const affected = await nxAffected(target); + + for (const project of affected.projects) { + const key = `${os}-${configuration}-${target}-${project}`; + const nxConfig = await getProjectNxConfig(project); + const paths = (nxConfig.targets?.[target]?.outputs || []).map((path) => { + return parsePath(path, project); + }); + + if (paths.length) { + await cache.restoreCache(paths, key); + + console.log('Successfully cached paths:'); + console.log(paths.join('\n')); + } else { + console.log('No outputs to cache'); + } + } +} + +run(); diff --git a/packages/client/package.json b/packages/client/package.json index ee3b18d4..bdc7114b 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -60,31 +60,31 @@ "targets": { "build": { "inputs": [ - "../../tsconfig.json", - "src/", - "angular.json", - "package.json", - "tailwind.config.js", - "tsconfig.app.json", - "tsconfig.json" + "{workspaceRoot}/tsconfig.json", + "{projectRoot}/src/", + "{projectRoot}/angular.json", + "{projectRoot}/package.json", + "{projectRoot}/tailwind.config.js", + "{projectRoot}/tsconfig.app.json", + "{projectRoot}/tsconfig.json" ], "outputs": [ - "dist/" + "{projectRoot}/dist/" ] }, "test": { "inputs": [ - "../../tsconfig.json", - "src/", - "angular.json", - "karma.conf.js", - "package.json", - "tailwind.config.js", - "tsconfig.json", - "tsconfig.spec.json" + "{workspaceRoot}/tsconfig.json", + "{projectRoot}/src/", + "{projectRoot}/angular.json", + "{projectRoot}/karma.conf.js", + "{projectRoot}/package.json", + "{projectRoot}/tailwind.config.js", + "{projectRoot}/tsconfig.json", + "{projectRoot}/tsconfig.spec.json" ], "outputs": [ - "coverage/" + "{projectRoot}/coverage/" ] } } From 3df4065a197453a72144b2fdd50477fb0c82b70f Mon Sep 17 00:00:00 2001 From: Marcin Czerniak Date: Wed, 29 Mar 2023 17:28:10 +0200 Subject: [PATCH 3/4] Change GitHub actions imports to dynamic imports --- .github/actions/cache-target-outputs/index.js | 2 +- .github/actions/restore-target-outputs/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/cache-target-outputs/index.js b/.github/actions/cache-target-outputs/index.js index 7c9059e4..a93d6212 100644 --- a/.github/actions/cache-target-outputs/index.js +++ b/.github/actions/cache-target-outputs/index.js @@ -1,8 +1,8 @@ const cache = require('@actions/cache'); const core = require('@actions/core'); -const { nxAffected } = require('../../../packages/tools/utils/nx-affected'); const { readFileSync, existsSync } = require('fs'); const { resolve } = require('path'); +const { nxAffected } = import('../../../packages/tools/utils/nx-affected'); /** * @param {string} project diff --git a/.github/actions/restore-target-outputs/index.js b/.github/actions/restore-target-outputs/index.js index c3f65ac3..1fc37b74 100644 --- a/.github/actions/restore-target-outputs/index.js +++ b/.github/actions/restore-target-outputs/index.js @@ -1,8 +1,8 @@ const cache = require('@actions/cache'); const core = require('@actions/core'); -const { nxAffected } = require('../../../packages/tools/utils/nx-affected'); const { readFileSync, existsSync } = require('fs'); const { resolve } = require('path'); +const { nxAffected } = import('../../../packages/tools/utils/nx-affected'); /** * @param {string} project From 22bfc20fe7b75803dd0af72bd138e3a1becc5105 Mon Sep 17 00:00:00 2001 From: Marcin Czerniak Date: Wed, 29 Mar 2023 17:33:21 +0200 Subject: [PATCH 4/4] Remove whitespace --- .github/workflows/_test.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/_test.yml b/.github/workflows/_test.yml index 84791322..15797e2f 100644 --- a/.github/workflows/_test.yml +++ b/.github/workflows/_test.yml @@ -47,4 +47,3 @@ jobs: with: target: test configuration: ${{ inputs.configuration }} -