From ce525f3289c37384973f38c659b68d8afa490f6e Mon Sep 17 00:00:00 2001 From: Pascal Jufer Date: Fri, 23 Sep 2022 10:56:38 +0200 Subject: [PATCH 1/8] Consistent `paths` patterns examples (#275) --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3c71c6a..834bd73 100644 --- a/README.md +++ b/README.md @@ -103,12 +103,12 @@ A YAML-string with named [`paths_ignore`](#paths_ignore) / [`paths`](#paths) pat ```yaml frontend: paths_ignore: - - 'frontend/docs/**/*' + - 'frontend/docs/**' paths: - - 'frontend/**/*' + - 'frontend/**' backend: paths: - - 'backend/**/*' + - 'backend/**' ### Here you can optionally control/limit backtracking # Boolean or number (default: true) # 'false' means disable backtracking completely @@ -313,12 +313,12 @@ jobs: paths_filter: | frontend: paths_ignore: - - 'frontend/docs/**/*' + - 'frontend/docs/**' paths: - - 'frontend/**/*' + - 'frontend/**' backend: paths: - - 'backend/**/*' + - 'backend/**' # Can be mixed with the "global" 'paths_ignore' / 'paths' options, for example: # paths_ignore: '["**/README.md"]' From aac2bd14f64141054c60afaca9f205fef66d0b63 Mon Sep 17 00:00:00 2001 From: Pascal Jufer Date: Fri, 23 Sep 2022 11:17:20 +0200 Subject: [PATCH 2/8] Consistent definitions of `if` conditions (#276) --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 834bd73..7bccfa8 100644 --- a/README.md +++ b/README.md @@ -267,7 +267,7 @@ jobs: main_job: needs: pre_job - if: ${{ needs.pre_job.outputs.should_skip != 'true' }} + if: needs.pre_job.outputs.should_skip != 'true' runs-on: ubuntu-latest steps: - run: echo "Running slow tests..." && sleep 30 @@ -288,7 +288,7 @@ jobs: with: cancel_others: 'false' paths: '["src/**", "dist/**"]' - - if: ${{ steps.skip_check.outputs.should_skip != 'true' }} + - if: steps.skip_check.outputs.should_skip != 'true' run: | echo "Run only if src/ or dist/ changed..." && sleep 30 echo "Do other stuff..." @@ -328,10 +328,10 @@ jobs: # been found) 'paths_result' outputs an empty object ('{}'). This can be easily intercepted in the if condition of a job # by checking the result of the "global" 'should_skip' output first. if: needs.pre_job.outputs.should_skip != 'true' || !fromJSON(needs.pre_job.outputs.paths_result).frontend.should_skip - ... + # ... backend: - ... + # ... ``` ## How does it work? From 3d95da3d525f87dd3c3a3e768b57374dc384b161 Mon Sep 17 00:00:00 2001 From: Pascal Jufer Date: Mon, 26 Sep 2022 13:15:28 +0200 Subject: [PATCH 3/8] Add a job summary (#277) --- .github/workflows/test.yml | 22 --- dist/index.js | 325 +++++++++++++++++++++---------------- package-lock.json | 189 +++++++++++---------- src/main.ts | 91 +++++++++-- 4 files changed, 364 insertions(+), 263 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0318f70..b53b65d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -37,28 +37,6 @@ jobs: skip_after_successful_duplicate: 'true' paths_ignore: '["**/README.md", "**/docs/**"]' - - name: Print outputs - run: | - echo '::group::should_skip' - echo '${{ steps.skip_check.outputs.should_skip }}' - echo '::endgroup::' - - echo '::group::reason' - echo '${{ steps.skip_check.outputs.reason }}' - echo '::endgroup::' - - echo '::group::skipped_by' - echo '${{ toJSON(fromJSON(steps.skip_check.outputs.skipped_by)) }}' - echo '::endgroup::' - - echo '::group::paths_result' - echo '${{ toJSON(fromJSON(steps.skip_check.outputs.paths_result)) }}' - echo '::endgroup::' - - echo '::group::changed_files' - echo '${{ toJSON(fromJSON(steps.skip_check.outputs.changed_files)) }}' - echo '::endgroup::' - main_job: needs: pre_job if: ${{ needs.pre_job.outputs.should_skip != 'true' }} diff --git a/dist/index.js b/dist/index.js index 08cc47a..4a3c215 100644 --- a/dist/index.js +++ b/dist/index.js @@ -77,7 +77,7 @@ class SkipDuplicateActions { // Abort early if current run has been triggered by an event that should never be skipped. if (this.inputs.doNotSkip.includes(this.context.currentRun.event)) { core.info(`Do not skip execution because the workflow was triggered with '${this.context.currentRun.event}'`); - exitSuccess({ + yield exitSuccess({ shouldSkip: false, reason: 'do_not_skip' }); @@ -87,7 +87,7 @@ class SkipDuplicateActions { const successfulDuplicateRun = this.findSuccessfulDuplicateRun(this.context.currentRun.treeHash); if (successfulDuplicateRun) { core.info(`Skip execution because the exact same files have been successfully checked in run ${successfulDuplicateRun.htmlUrl}`); - exitSuccess({ + yield exitSuccess({ shouldSkip: true, reason: 'skip_after_successful_duplicate', skippedBy: successfulDuplicateRun @@ -98,7 +98,7 @@ class SkipDuplicateActions { if (this.inputs.concurrentSkipping !== 'never') { const concurrentRun = this.detectConcurrentRuns(); if (concurrentRun) { - exitSuccess({ + yield exitSuccess({ shouldSkip: true, reason: 'concurrent_skipping', skippedBy: concurrentRun @@ -110,19 +110,19 @@ class SkipDuplicateActions { this.inputs.pathsIgnore.length >= 1 || Object.keys(this.inputs.pathsFilter).length >= 1) { const { changedFiles, pathsResult } = yield this.backtracePathSkipping(); - exitSuccess({ + yield exitSuccess({ shouldSkip: pathsResult.global.should_skip === 'unknown' ? false : pathsResult.global.should_skip, reason: 'paths', skippedBy: pathsResult.global.skipped_by, - changedFiles, - pathsResult + pathsResult, + changedFiles }); } // Do not skip otherwise. core.info('Do not skip execution because we did not find a transferable run'); - exitSuccess({ + yield exitSuccess({ shouldSkip: false, reason: 'no_transferable_run' }); @@ -226,7 +226,11 @@ class SkipDuplicateActions { .map(file => file.filename) .filter(file => typeof file === 'string') : []; - allChangedFiles.push(changedFiles); + allChangedFiles.push({ + sha: commit.sha, + htmlUrl: commit.html_url, + changedFiles + }); const successfulRun = (distanceToHEAD >= 1 && this.findSuccessfulDuplicateRun(commit.commit.tree.sha)) || undefined; @@ -277,7 +281,7 @@ class SkipDuplicateActions { break; } } while (Object.keys(pathsResult).some(path => pathsResult[path].should_skip === 'unknown')); - return { changedFiles: allChangedFiles, pathsResult }; + return { pathsResult, changedFiles: allChangedFiles }; }); } isCommitPathsIgnored(changedFiles, pathsIgnore) { @@ -387,12 +391,44 @@ function mapWorkflowRun(run, treeHash) { } /** Set all outputs and exit the action. */ function exitSuccess(args) { - core.setOutput('should_skip', args.shouldSkip); - core.setOutput('reason', args.reason); - core.setOutput('skipped_by', args.skippedBy || {}); - core.setOutput('changed_files', args.changedFiles || []); - core.setOutput('paths_result', args.pathsResult || {}); - process.exit(0); + var _a; + return __awaiter(this, void 0, void 0, function* () { + const summary = [ + '

Skip Duplicate Actions

', + '', + '', + '', + ``, + '', + '', + '', + ``, + '' + ]; + if (args.skippedBy) { + summary.push('', '', ``, ''); + } + if (args.pathsResult) { + summary.push('', '', ``, ''); + } + if (args.changedFiles) { + const changedFiles = args.changedFiles + .map(commit => `${commit.sha.substring(0, 7)}: +
    ${commit.changedFiles + .map(file => `
  • ${file}
  • `) + .join('')}
`) + .join(''); + summary.push('', '', ``, ''); + } + summary.push('
Should Skip${args.shouldSkip ? 'Yes' : 'No'} (${args.shouldSkip})
Reason${args.reason}
Skipped By${args.skippedBy.runNumber}
Paths Result
${JSON.stringify(args.pathsResult, null, 2)}
Changed Files${changedFiles}
'); + yield core.summary.addRaw(summary.join('')).write(); + core.setOutput('should_skip', args.shouldSkip); + core.setOutput('reason', args.reason); + core.setOutput('skipped_by', args.skippedBy || {}); + core.setOutput('paths_result', args.pathsResult || {}); + core.setOutput('changed_files', ((_a = args.changedFiles) === null || _a === void 0 ? void 0 : _a.map(commit => commit.changedFiles)) || []); + process.exit(0); + }); } /** Immediately terminate the action with failing exit code. */ function exitFail(error) { @@ -1572,8 +1608,9 @@ exports.context = new Context.Context(); * @param token the repo PAT or GITHUB_TOKEN * @param options other options to set */ -function getOctokit(token, options) { - return new utils_1.GitHub(utils_1.getOctokitOptions(token, options)); +function getOctokit(token, options, ...additionalPlugins) { + const GitHubWithPlugins = utils_1.GitHub.plugin(...additionalPlugins); + return new GitHubWithPlugins(utils_1.getOctokitOptions(token, options)); } exports.getOctokit = getOctokit; //# sourceMappingURL=github.js.map @@ -2533,7 +2570,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); var universalUserAgent = __nccwpck_require__(5030); var beforeAfterHook = __nccwpck_require__(3682); var request = __nccwpck_require__(6234); -var graphql = __nccwpck_require__(6442); +var graphql = __nccwpck_require__(8467); var authToken = __nccwpck_require__(334); function _objectWithoutPropertiesLoose(source, excluded) { @@ -2704,132 +2741,6 @@ exports.Octokit = Octokit; //# sourceMappingURL=index.js.map -/***/ }), - -/***/ 6442: -/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", ({ value: true })); - -var request = __nccwpck_require__(6234); -var universalUserAgent = __nccwpck_require__(5030); - -const VERSION = "4.8.0"; - -function _buildMessageForResponseErrors(data) { - return `Request failed due to following response errors:\n` + data.errors.map(e => ` - ${e.message}`).join("\n"); -} - -class GraphqlResponseError extends Error { - constructor(request, headers, response) { - super(_buildMessageForResponseErrors(response)); - this.request = request; - this.headers = headers; - this.response = response; - this.name = "GraphqlResponseError"; // Expose the errors and response data in their shorthand properties. - - this.errors = response.errors; - this.data = response.data; // Maintains proper stack trace (only available on V8) - - /* istanbul ignore next */ - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, this.constructor); - } - } - -} - -const NON_VARIABLE_OPTIONS = ["method", "baseUrl", "url", "headers", "request", "query", "mediaType"]; -const FORBIDDEN_VARIABLE_OPTIONS = ["query", "method", "url"]; -const GHES_V3_SUFFIX_REGEX = /\/api\/v3\/?$/; -function graphql(request, query, options) { - if (options) { - if (typeof query === "string" && "query" in options) { - return Promise.reject(new Error(`[@octokit/graphql] "query" cannot be used as variable name`)); - } - - for (const key in options) { - if (!FORBIDDEN_VARIABLE_OPTIONS.includes(key)) continue; - return Promise.reject(new Error(`[@octokit/graphql] "${key}" cannot be used as variable name`)); - } - } - - const parsedOptions = typeof query === "string" ? Object.assign({ - query - }, options) : query; - const requestOptions = Object.keys(parsedOptions).reduce((result, key) => { - if (NON_VARIABLE_OPTIONS.includes(key)) { - result[key] = parsedOptions[key]; - return result; - } - - if (!result.variables) { - result.variables = {}; - } - - result.variables[key] = parsedOptions[key]; - return result; - }, {}); // workaround for GitHub Enterprise baseUrl set with /api/v3 suffix - // https://github.com/octokit/auth-app.js/issues/111#issuecomment-657610451 - - const baseUrl = parsedOptions.baseUrl || request.endpoint.DEFAULTS.baseUrl; - - if (GHES_V3_SUFFIX_REGEX.test(baseUrl)) { - requestOptions.url = baseUrl.replace(GHES_V3_SUFFIX_REGEX, "/api/graphql"); - } - - return request(requestOptions).then(response => { - if (response.data.errors) { - const headers = {}; - - for (const key of Object.keys(response.headers)) { - headers[key] = response.headers[key]; - } - - throw new GraphqlResponseError(requestOptions, headers, response.data); - } - - return response.data.data; - }); -} - -function withDefaults(request$1, newDefaults) { - const newRequest = request$1.defaults(newDefaults); - - const newApi = (query, options) => { - return graphql(newRequest, query, options); - }; - - return Object.assign(newApi, { - defaults: withDefaults.bind(null, newRequest), - endpoint: request.request.endpoint - }); -} - -const graphql$1 = withDefaults(request.request, { - headers: { - "user-agent": `octokit-graphql.js/${VERSION} ${universalUserAgent.getUserAgent()}` - }, - method: "POST", - url: "/https/github.com/graphql" -}); -function withCustomRequest(customRequest) { - return withDefaults(customRequest, { - method: "POST", - url: "/https/github.com/graphql" - }); -} - -exports.GraphqlResponseError = GraphqlResponseError; -exports.graphql = graphql$1; -exports.withCustomRequest = withCustomRequest; -//# sourceMappingURL=index.js.map - - /***/ }), /***/ 9440: @@ -3228,6 +3139,132 @@ exports.endpoint = endpoint; //# sourceMappingURL=index.js.map +/***/ }), + +/***/ 8467: +/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", ({ value: true })); + +var request = __nccwpck_require__(6234); +var universalUserAgent = __nccwpck_require__(5030); + +const VERSION = "4.8.0"; + +function _buildMessageForResponseErrors(data) { + return `Request failed due to following response errors:\n` + data.errors.map(e => ` - ${e.message}`).join("\n"); +} + +class GraphqlResponseError extends Error { + constructor(request, headers, response) { + super(_buildMessageForResponseErrors(response)); + this.request = request; + this.headers = headers; + this.response = response; + this.name = "GraphqlResponseError"; // Expose the errors and response data in their shorthand properties. + + this.errors = response.errors; + this.data = response.data; // Maintains proper stack trace (only available on V8) + + /* istanbul ignore next */ + + if (Error.captureStackTrace) { + Error.captureStackTrace(this, this.constructor); + } + } + +} + +const NON_VARIABLE_OPTIONS = ["method", "baseUrl", "url", "headers", "request", "query", "mediaType"]; +const FORBIDDEN_VARIABLE_OPTIONS = ["query", "method", "url"]; +const GHES_V3_SUFFIX_REGEX = /\/api\/v3\/?$/; +function graphql(request, query, options) { + if (options) { + if (typeof query === "string" && "query" in options) { + return Promise.reject(new Error(`[@octokit/graphql] "query" cannot be used as variable name`)); + } + + for (const key in options) { + if (!FORBIDDEN_VARIABLE_OPTIONS.includes(key)) continue; + return Promise.reject(new Error(`[@octokit/graphql] "${key}" cannot be used as variable name`)); + } + } + + const parsedOptions = typeof query === "string" ? Object.assign({ + query + }, options) : query; + const requestOptions = Object.keys(parsedOptions).reduce((result, key) => { + if (NON_VARIABLE_OPTIONS.includes(key)) { + result[key] = parsedOptions[key]; + return result; + } + + if (!result.variables) { + result.variables = {}; + } + + result.variables[key] = parsedOptions[key]; + return result; + }, {}); // workaround for GitHub Enterprise baseUrl set with /api/v3 suffix + // https://github.com/octokit/auth-app.js/issues/111#issuecomment-657610451 + + const baseUrl = parsedOptions.baseUrl || request.endpoint.DEFAULTS.baseUrl; + + if (GHES_V3_SUFFIX_REGEX.test(baseUrl)) { + requestOptions.url = baseUrl.replace(GHES_V3_SUFFIX_REGEX, "/api/graphql"); + } + + return request(requestOptions).then(response => { + if (response.data.errors) { + const headers = {}; + + for (const key of Object.keys(response.headers)) { + headers[key] = response.headers[key]; + } + + throw new GraphqlResponseError(requestOptions, headers, response.data); + } + + return response.data.data; + }); +} + +function withDefaults(request$1, newDefaults) { + const newRequest = request$1.defaults(newDefaults); + + const newApi = (query, options) => { + return graphql(newRequest, query, options); + }; + + return Object.assign(newApi, { + defaults: withDefaults.bind(null, newRequest), + endpoint: request.request.endpoint + }); +} + +const graphql$1 = withDefaults(request.request, { + headers: { + "user-agent": `octokit-graphql.js/${VERSION} ${universalUserAgent.getUserAgent()}` + }, + method: "POST", + url: "/https/github.com/graphql" +}); +function withCustomRequest(customRequest) { + return withDefaults(customRequest, { + method: "POST", + url: "/https/github.com/graphql" + }); +} + +exports.GraphqlResponseError = GraphqlResponseError; +exports.graphql = graphql$1; +exports.withCustomRequest = withCustomRequest; +//# sourceMappingURL=index.js.map + + /***/ }), /***/ 4193: diff --git a/package-lock.json b/package-lock.json index c05d16c..b48e683 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,9 +35,9 @@ } }, "node_modules/@actions/github": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.3.tgz", - "integrity": "sha512-myjA/pdLQfhUGLtRZC/J4L1RXOG4o6aYdiEq+zr5wVVKljzbFld+xv10k1FX6IkIJtNxbAq44BdwSNpQ015P0A==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz", + "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==", "dependencies": { "@actions/http-client": "^2.0.1", "@octokit/core": "^3.6.0", @@ -102,9 +102,9 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", - "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==", + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz", + "integrity": "sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", @@ -201,16 +201,6 @@ "universal-user-agent": "^6.0.0" } }, - "node_modules/@octokit/core/node_modules/@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "dependencies": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - }, "node_modules/@octokit/endpoint": { "version": "6.0.12", "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", @@ -221,6 +211,16 @@ "universal-user-agent": "^6.0.0" } }, + "node_modules/@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "dependencies": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, "node_modules/@octokit/openapi-types": { "version": "12.11.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", @@ -314,9 +314,9 @@ } }, "node_modules/@types/node": { - "version": "16.11.59", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.59.tgz", - "integrity": "sha512-6u+36Dj3aDzhfBVUf/mfmc92OEdzQ2kx2jcXGdigfl70E/neV21ZHE6UCz4MDzTRcVqGAM27fk+DLXvyDsn3Jw==", + "version": "16.11.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.60.tgz", + "integrity": "sha512-kYIYa1D1L+HDv5M5RXQeEu1o0FKA6yedZIoyugm/MBPROkLpX4L7HRxMrPVyo8bnvjpW/wDlqFNGzXNMb7AdRw==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { @@ -741,9 +741,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001406", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001406.tgz", - "integrity": "sha512-bWTlaXUy/rq0BBtYShc/jArYfBPjEV95euvZ8JVtO43oQExEN/WquoqpufFjNu4kSpi5cy5kMbNvzztWDfv1Jg==", + "version": "1.0.30001412", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001412.tgz", + "integrity": "sha512-+TeEIee1gS5bYOiuf+PS/kp2mrXic37Hl66VY6EAfxasIk5fELTktK2oOezYed12H8w7jt3s512PpulQidPjwA==", "dev": true, "funding": [ { @@ -797,9 +797,9 @@ "dev": true }, "node_modules/core-js-pure": { - "version": "3.25.2", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.2.tgz", - "integrity": "sha512-ItD7YpW1cUB4jaqFLZXe1AXkyqIxz6GqPnsDV4uF4hVcWh/WAGIqSqw5p0/WdsILM0Xht9s3Koyw05R3K6RtiA==", + "version": "3.25.3", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.3.tgz", + "integrity": "sha512-T/7qvgv70MEvRkZ8p6BasLZmOVYKzOaWNBEHAU8FmveCJkl4nko2quqPQOmy6AJIp5MBanhz9no3A94NoRb0XA==", "dev": true, "hasInstallScript": true, "funding": { @@ -896,9 +896,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.254", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.254.tgz", - "integrity": "sha512-Sh/7YsHqQYkA6ZHuHMy24e6TE4eX6KZVsZb9E/DvU1nQRIrH4BflO/4k+83tfdYvDl+MObvlqHPRICzEdC9c6Q==", + "version": "1.4.262", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.262.tgz", + "integrity": "sha512-Ckn5haqmGh/xS8IbcgK3dnwAVnhDyo/WQnklWn6yaMucYTq7NNxwlGE8ElzEOnonzRLzUCo2Ot3vUb2GYUF2Hw==", "dev": true }, "node_modules/emoji-regex": { @@ -908,22 +908,22 @@ "dev": true }, "node_modules/es-abstract": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.2.tgz", - "integrity": "sha512-XxXQuVNrySBNlEkTYJoDNFe5+s2yIOpzq80sUHEdPdQr0S5nTLz4ZPPPswNIpKseDDUS5yghX1gfLIHQZ1iNuQ==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.3.tgz", + "integrity": "sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw==", "dev": true, "dependencies": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.2", + "get-intrinsic": "^1.1.3", "get-symbol-description": "^1.0.0", "has": "^1.0.3", "has-property-descriptors": "^1.0.0", "has-symbols": "^1.0.3", "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", + "is-callable": "^1.2.6", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", @@ -933,6 +933,7 @@ "object-keys": "^1.1.1", "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", "string.prototype.trimend": "^1.0.5", "string.prototype.trimstart": "^1.0.5", "unbox-primitive": "^1.0.2" @@ -992,13 +993,13 @@ } }, "node_modules/eslint": { - "version": "8.23.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.1.tgz", - "integrity": "sha512-w7C1IXCc6fNqjpuYd0yPlcTKKmHlHHktRkzmBPZ+7cvNBQuiNjx0xaMTjAJGCafJhQkrFJooREv0CtrVzmHwqg==", + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.24.0.tgz", + "integrity": "sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ==", "dev": true, "dependencies": { "@eslint/eslintrc": "^1.3.2", - "@humanwhocodes/config-array": "^0.10.4", + "@humanwhocodes/config-array": "^0.10.5", "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", "@humanwhocodes/module-importer": "^1.0.1", "ajv": "^6.10.0", @@ -1897,9 +1898,9 @@ } }, "node_modules/is-callable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.6.tgz", - "integrity": "sha512-krO72EO2NptOGAX2KYyqbP9vYMlNAXdB53rq6f8LXY6RY7JdSR/3BD6wLUlPHSAesmY9vstNrjvqGaCiRK/91Q==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, "engines": { "node": ">= 0.4" @@ -2643,6 +2644,20 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/semver": { "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", @@ -3049,9 +3064,9 @@ } }, "@actions/github": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.0.3.tgz", - "integrity": "sha512-myjA/pdLQfhUGLtRZC/J4L1RXOG4o6aYdiEq+zr5wVVKljzbFld+xv10k1FX6IkIJtNxbAq44BdwSNpQ015P0A==", + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz", + "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==", "requires": { "@actions/http-client": "^2.0.1", "@octokit/core": "^3.6.0", @@ -3104,9 +3119,9 @@ } }, "@humanwhocodes/config-array": { - "version": "0.10.4", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.4.tgz", - "integrity": "sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw==", + "version": "0.10.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz", + "integrity": "sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", @@ -3178,18 +3193,6 @@ "@octokit/types": "^6.0.3", "before-after-hook": "^2.2.0", "universal-user-agent": "^6.0.0" - }, - "dependencies": { - "@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "requires": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - } } }, "@octokit/endpoint": { @@ -3202,6 +3205,16 @@ "universal-user-agent": "^6.0.0" } }, + "@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "requires": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, "@octokit/openapi-types": { "version": "12.11.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", @@ -3289,9 +3302,9 @@ } }, "@types/node": { - "version": "16.11.59", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.59.tgz", - "integrity": "sha512-6u+36Dj3aDzhfBVUf/mfmc92OEdzQ2kx2jcXGdigfl70E/neV21ZHE6UCz4MDzTRcVqGAM27fk+DLXvyDsn3Jw==", + "version": "16.11.60", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.60.tgz", + "integrity": "sha512-kYIYa1D1L+HDv5M5RXQeEu1o0FKA6yedZIoyugm/MBPROkLpX4L7HRxMrPVyo8bnvjpW/wDlqFNGzXNMb7AdRw==", "dev": true }, "@typescript-eslint/eslint-plugin": { @@ -3557,9 +3570,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001406", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001406.tgz", - "integrity": "sha512-bWTlaXUy/rq0BBtYShc/jArYfBPjEV95euvZ8JVtO43oQExEN/WquoqpufFjNu4kSpi5cy5kMbNvzztWDfv1Jg==", + "version": "1.0.30001412", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001412.tgz", + "integrity": "sha512-+TeEIee1gS5bYOiuf+PS/kp2mrXic37Hl66VY6EAfxasIk5fELTktK2oOezYed12H8w7jt3s512PpulQidPjwA==", "dev": true }, "chalk": { @@ -3594,9 +3607,9 @@ "dev": true }, "core-js-pure": { - "version": "3.25.2", - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.2.tgz", - "integrity": "sha512-ItD7YpW1cUB4jaqFLZXe1AXkyqIxz6GqPnsDV4uF4hVcWh/WAGIqSqw5p0/WdsILM0Xht9s3Koyw05R3K6RtiA==", + "version": "3.25.3", + "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.25.3.tgz", + "integrity": "sha512-T/7qvgv70MEvRkZ8p6BasLZmOVYKzOaWNBEHAU8FmveCJkl4nko2quqPQOmy6AJIp5MBanhz9no3A94NoRb0XA==", "dev": true }, "cross-spawn": { @@ -3665,9 +3678,9 @@ } }, "electron-to-chromium": { - "version": "1.4.254", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.254.tgz", - "integrity": "sha512-Sh/7YsHqQYkA6ZHuHMy24e6TE4eX6KZVsZb9E/DvU1nQRIrH4BflO/4k+83tfdYvDl+MObvlqHPRICzEdC9c6Q==", + "version": "1.4.262", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.262.tgz", + "integrity": "sha512-Ckn5haqmGh/xS8IbcgK3dnwAVnhDyo/WQnklWn6yaMucYTq7NNxwlGE8ElzEOnonzRLzUCo2Ot3vUb2GYUF2Hw==", "dev": true }, "emoji-regex": { @@ -3677,22 +3690,22 @@ "dev": true }, "es-abstract": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.2.tgz", - "integrity": "sha512-XxXQuVNrySBNlEkTYJoDNFe5+s2yIOpzq80sUHEdPdQr0S5nTLz4ZPPPswNIpKseDDUS5yghX1gfLIHQZ1iNuQ==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.20.3.tgz", + "integrity": "sha512-AyrnaKVpMzljIdwjzrj+LxGmj8ik2LckwXacHqrJJ/jxz6dDDBcZ7I7nlHM0FvEW8MfbWJwOd+yT2XzYW49Frw==", "dev": true, "requires": { "call-bind": "^1.0.2", "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.1.2", + "get-intrinsic": "^1.1.3", "get-symbol-description": "^1.0.0", "has": "^1.0.3", "has-property-descriptors": "^1.0.0", "has-symbols": "^1.0.3", "internal-slot": "^1.0.3", - "is-callable": "^1.2.4", + "is-callable": "^1.2.6", "is-negative-zero": "^2.0.2", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", @@ -3702,6 +3715,7 @@ "object-keys": "^1.1.1", "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.4.3", + "safe-regex-test": "^1.0.0", "string.prototype.trimend": "^1.0.5", "string.prototype.trimstart": "^1.0.5", "unbox-primitive": "^1.0.2" @@ -3740,13 +3754,13 @@ "dev": true }, "eslint": { - "version": "8.23.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.23.1.tgz", - "integrity": "sha512-w7C1IXCc6fNqjpuYd0yPlcTKKmHlHHktRkzmBPZ+7cvNBQuiNjx0xaMTjAJGCafJhQkrFJooREv0CtrVzmHwqg==", + "version": "8.24.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.24.0.tgz", + "integrity": "sha512-dWFaPhGhTAiPcCgm3f6LI2MBWbogMnTJzFBbhXVRQDJPkr9pGZvVjlVfXd+vyDcWPA2Ic9L2AXPIQM0+vk/cSQ==", "dev": true, "requires": { "@eslint/eslintrc": "^1.3.2", - "@humanwhocodes/config-array": "^0.10.4", + "@humanwhocodes/config-array": "^0.10.5", "@humanwhocodes/gitignore-to-minimatch": "^1.0.2", "@humanwhocodes/module-importer": "^1.0.1", "ajv": "^6.10.0", @@ -4425,9 +4439,9 @@ } }, "is-callable": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.6.tgz", - "integrity": "sha512-krO72EO2NptOGAX2KYyqbP9vYMlNAXdB53rq6f8LXY6RY7JdSR/3BD6wLUlPHSAesmY9vstNrjvqGaCiRK/91Q==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true }, "is-core-module": { @@ -4936,6 +4950,17 @@ "queue-microtask": "^1.2.2" } }, + "safe-regex-test": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", + "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "is-regex": "^1.1.4" + } + }, "semver": { "version": "7.3.7", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", diff --git a/src/main.ts b/src/main.ts index e6602c5..0777fa8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -46,6 +46,8 @@ interface WorkflowRun { createdAt: string } +type ChangedFiles = {sha: string; htmlUrl: string; changedFiles: string[]}[] + type PathsFilter = Record< string, { @@ -115,7 +117,7 @@ class SkipDuplicateActions { core.info( `Do not skip execution because the workflow was triggered with '${this.context.currentRun.event}'` ) - exitSuccess({ + await exitSuccess({ shouldSkip: false, reason: 'do_not_skip' }) @@ -130,7 +132,7 @@ class SkipDuplicateActions { core.info( `Skip execution because the exact same files have been successfully checked in run ${successfulDuplicateRun.htmlUrl}` ) - exitSuccess({ + await exitSuccess({ shouldSkip: true, reason: 'skip_after_successful_duplicate', skippedBy: successfulDuplicateRun @@ -142,7 +144,7 @@ class SkipDuplicateActions { if (this.inputs.concurrentSkipping !== 'never') { const concurrentRun = this.detectConcurrentRuns() if (concurrentRun) { - exitSuccess({ + await exitSuccess({ shouldSkip: true, reason: 'concurrent_skipping', skippedBy: concurrentRun @@ -157,15 +159,15 @@ class SkipDuplicateActions { Object.keys(this.inputs.pathsFilter).length >= 1 ) { const {changedFiles, pathsResult} = await this.backtracePathSkipping() - exitSuccess({ + await exitSuccess({ shouldSkip: pathsResult.global.should_skip === 'unknown' ? false : pathsResult.global.should_skip, reason: 'paths', skippedBy: pathsResult.global.skipped_by, - changedFiles, - pathsResult + pathsResult, + changedFiles }) } @@ -173,7 +175,7 @@ class SkipDuplicateActions { core.info( 'Do not skip execution because we did not find a transferable run' ) - exitSuccess({ + await exitSuccess({ shouldSkip: false, reason: 'no_transferable_run' }) @@ -277,13 +279,13 @@ class SkipDuplicateActions { } async backtracePathSkipping(): Promise<{ - changedFiles: string[][] pathsResult: PathsResult + changedFiles: ChangedFiles }> { let commit: ApiCommit | null let iterSha: string | null = this.context.currentRun.commitHash let distanceToHEAD = 0 - const allChangedFiles: string[][] = [] + const allChangedFiles: ChangedFiles = [] const pathsFilter: PathsFilter = { ...this.inputs.pathsFilter, @@ -310,7 +312,11 @@ class SkipDuplicateActions { .map(file => file.filename) .filter(file => typeof file === 'string') : [] - allChangedFiles.push(changedFiles) + allChangedFiles.push({ + sha: commit.sha, + htmlUrl: commit.html_url, + changedFiles + }) const successfulRun = (distanceToHEAD >= 1 && @@ -395,7 +401,7 @@ class SkipDuplicateActions { ) ) - return {changedFiles: allChangedFiles, pathsResult} + return {pathsResult, changedFiles: allChangedFiles} } isCommitPathsIgnored(changedFiles: string[], pathsIgnore: string[]): boolean { @@ -533,18 +539,73 @@ function mapWorkflowRun( } /** Set all outputs and exit the action. */ -function exitSuccess(args: { +async function exitSuccess(args: { shouldSkip: boolean reason: string skippedBy?: WorkflowRun - changedFiles?: string[][] pathsResult?: PathsResult -}): never { + changedFiles?: ChangedFiles +}): Promise { + const summary = [ + '

Skip Duplicate Actions

', + '', + '', + '', + ``, + '', + '', + '', + ``, + '' + ] + if (args.skippedBy) { + summary.push( + '', + '', + ``, + '' + ) + } + if (args.pathsResult) { + summary.push( + '', + '', + ``, + '' + ) + } + if (args.changedFiles) { + const changedFiles = args.changedFiles + .map( + commit => + `${commit.sha.substring(0, 7)}: +
    ${commit.changedFiles + .map(file => `
  • ${file}
  • `) + .join('')}
` + ) + .join('') + summary.push( + '', + '', + ``, + '' + ) + } + summary.push('
Should Skip${args.shouldSkip ? 'Yes' : 'No'} (${args.shouldSkip})
Reason${args.reason}
Skipped By${args.skippedBy.runNumber}
Paths Result
${JSON.stringify(
+        args.pathsResult,
+        null,
+        2
+      )}
Changed Files${changedFiles}
') + await core.summary.addRaw(summary.join('')).write() + core.setOutput('should_skip', args.shouldSkip) core.setOutput('reason', args.reason) core.setOutput('skipped_by', args.skippedBy || {}) - core.setOutput('changed_files', args.changedFiles || []) core.setOutput('paths_result', args.pathsResult || {}) + core.setOutput( + 'changed_files', + args.changedFiles?.map(commit => commit.changedFiles) || [] + ) process.exit(0) } From 8d7e744695c04ddb8c228574dc1c127e38238098 Mon Sep 17 00:00:00 2001 From: Felix K <17876666+fkirc@users.noreply.github.com> Date: Tue, 27 Sep 2022 00:40:33 +0200 Subject: [PATCH 4/8] Cleanup README (#278) --- README.md | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 7bccfa8..7dbccfc 100644 --- a/README.md +++ b/README.md @@ -346,23 +346,21 @@ After querying such workflow runs, it will compare them with the current workflo ## How does path-skipping work? As mentioned above, `skip-duplicate-actions` provides a path-skipping functionality that is somewhat similar to GitHub's native `paths` and `paths_ignore` functionality. -However, path-skipping is not entirely trivial because there exist multiple options on how to do path-skipping. -Depending on your project, you might want to choose one of the following options: +However, path-skipping is not entirely trivial because there exist multiple options on how to do path-skipping: ### Option 1: Only look at the "current" commit -This is the thing that GitHub is currently doing, and I consider it as insufficient because it doesn't work for "required" checks. -Another problem is that the outcomes can be heavily dependent on which commits were pushed at which time, instead of the actual content that was pushed. +This is the thing that GitHub is currently doing, and we consider it as insufficient because it does not work for "required" checks. +Another problem is that the outcomes can be heavily dependent on the pushing-sequence of commits. ### Option 2: Look at Pull-Request-diffs -This option is probably implemented by https://github.com/dorny/paths-filter. -PR-diffs are simple to understand, but not everyone is using PRs for everything, so this is not an option for everyone. +PR-diffs are simple to understand, but they only work after opening a PR, not immediately after pushing a feature-branch. ### Option 3: Look for successful checks of previous commits -This is my personal favorite option and this is implemented by `skip-duplicate-actions`. -An advantage is that this works regardless of whether you are using PRs or feature-branches, and of course it also works for "required" checks. +This option is implemented by `skip-duplicate-actions`. +An advantage is that this works regardless of whether you are using PRs or raw feature-branches, and of course it also works for "required" checks. Internally, `skip-duplicate-actions` uses the [Repos Commit API](https://docs.github.com/en/rest/reference/repos#get-a-commit) to perform an efficient backtracking-algorithm for paths-skipping-detection. ## Maintainers From ed436fab56a842877f6657839514c65adcfe1932 Mon Sep 17 00:00:00 2001 From: Pascal Jufer Date: Tue, 27 Sep 2022 10:38:27 +0200 Subject: [PATCH 5/8] Add graphical representation of backtracking-algorithm (#279) --- README.md | 41 +++++++++++ package-lock.json | 184 +++++++++++++++++++++++----------------------- 2 files changed, 133 insertions(+), 92 deletions(-) diff --git a/README.md b/README.md index 7dbccfc..8b4ff8f 100644 --- a/README.md +++ b/README.md @@ -363,6 +363,47 @@ This option is implemented by `skip-duplicate-actions`. An advantage is that this works regardless of whether you are using PRs or raw feature-branches, and of course it also works for "required" checks. Internally, `skip-duplicate-actions` uses the [Repos Commit API](https://docs.github.com/en/rest/reference/repos#get-a-commit) to perform an efficient backtracking-algorithm for paths-skipping-detection. +This is how the algorithm works approximately: + +```mermaid +stateDiagram-v2 + Check_Commit: Check Commit + [*] --> Check_Commit: Current commit + + state Path_Ignored <> + Check_Commit --> Path_Ignored: Do all changed files match against "paths_ignore"? + Ignored_Yes: Yes + Ignored_No: No + Path_Ignored --> Ignored_Yes + Path_Ignored --> Ignored_No + + state Path_Skipped <> + Ignored_No --> Path_Skipped: Do none of the changed files match against "paths"? + Skipped_Yes: Yes + Skipped_No: No + Path_Skipped --> Skipped_Yes: No matches + Path_Skipped --> Skipped_No: Some matches + + Parent_Commit: Fetch Parent Commit + Ignored_Yes --> Parent_Commit + Skipped_Yes --> Parent_Commit + + state Successful_Run <> + Parent_Commit --> Successful_Run: Is there a successful run for this commit? + Run_Yes: Yes + Run_No: No + Successful_Run --> Run_Yes + Successful_Run --> Run_No + + Run_No --> Check_Commit: Parent commit + + Skip: Skip! + Run_Yes --> Skip: (Because all changes since this run are in ignored or skipped paths) + + Dont_Skip: Don't Skip! + Skipped_No --> Dont_Skip: (Because changed files needs to be "tested") +``` + ## Maintainers - [@paescuj](https://github.com/paescuj) diff --git a/package-lock.json b/package-lock.json index b48e683..e7d19e8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -314,20 +314,20 @@ } }, "node_modules/@types/node": { - "version": "16.11.60", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.60.tgz", - "integrity": "sha512-kYIYa1D1L+HDv5M5RXQeEu1o0FKA6yedZIoyugm/MBPROkLpX4L7HRxMrPVyo8bnvjpW/wDlqFNGzXNMb7AdRw==", + "version": "16.11.62", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.62.tgz", + "integrity": "sha512-K/ggecSdwAAy2NUW4WKmF4Rc03GKbsfP+k326UWgckoS+Rzd2PaWbjk76dSmqdLQvLTJAO9axiTUJ6488mFsYQ==", "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.0.tgz", - "integrity": "sha512-GgHi/GNuUbTOeoJiEANi0oI6fF3gBQc3bGFYj40nnAPCbhrtEDf2rjBmefFadweBmO1Du1YovHeDP2h5JLhtTQ==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.1.tgz", + "integrity": "sha512-ky7EFzPhqz3XlhS7vPOoMDaQnQMn+9o5ICR9CPr/6bw8HrFkzhMSxuA3gRfiJVvs7geYrSeawGJjZoZQKCOglQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/type-utils": "5.38.0", - "@typescript-eslint/utils": "5.38.0", + "@typescript-eslint/scope-manager": "5.38.1", + "@typescript-eslint/type-utils": "5.38.1", + "@typescript-eslint/utils": "5.38.1", "debug": "^4.3.4", "ignore": "^5.2.0", "regexpp": "^3.2.0", @@ -352,14 +352,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.38.0.tgz", - "integrity": "sha512-/F63giJGLDr0ms1Cr8utDAxP2SPiglaD6V+pCOcG35P2jCqdfR7uuEhz1GIC3oy4hkUF8xA1XSXmd9hOh/a5EA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.38.1.tgz", + "integrity": "sha512-LDqxZBVFFQnQRz9rUZJhLmox+Ep5kdUmLatLQnCRR6523YV+XhRjfYzStQ4MheFA8kMAfUlclHSbu+RKdRwQKw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/typescript-estree": "5.38.0", + "@typescript-eslint/scope-manager": "5.38.1", + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/typescript-estree": "5.38.1", "debug": "^4.3.4" }, "engines": { @@ -379,13 +379,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.38.0.tgz", - "integrity": "sha512-ByhHIuNyKD9giwkkLqzezZ9y5bALW8VNY6xXcP+VxoH4JBDKjU5WNnsiD4HJdglHECdV+lyaxhvQjTUbRboiTA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.38.1.tgz", + "integrity": "sha512-BfRDq5RidVU3RbqApKmS7RFMtkyWMM50qWnDAkKgQiezRtLKsoyRKIvz1Ok5ilRWeD9IuHvaidaLxvGx/2eqTQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/visitor-keys": "5.38.0" + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/visitor-keys": "5.38.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -396,13 +396,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.38.0.tgz", - "integrity": "sha512-iZq5USgybUcj/lfnbuelJ0j3K9dbs1I3RICAJY9NZZpDgBYXmuUlYQGzftpQA9wC8cKgtS6DASTvF3HrXwwozA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.38.1.tgz", + "integrity": "sha512-UU3j43TM66gYtzo15ivK2ZFoDFKKP0k03MItzLdq0zV92CeGCXRfXlfQX5ILdd4/DSpHkSjIgLLLh1NtkOJOAw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.38.0", - "@typescript-eslint/utils": "5.38.0", + "@typescript-eslint/typescript-estree": "5.38.1", + "@typescript-eslint/utils": "5.38.1", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -423,9 +423,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.38.0.tgz", - "integrity": "sha512-HHu4yMjJ7i3Cb+8NUuRCdOGu2VMkfmKyIJsOr9PfkBVYLYrtMCK/Ap50Rpov+iKpxDTfnqvDbuPLgBE5FwUNfA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.38.1.tgz", + "integrity": "sha512-QTW1iHq1Tffp9lNfbfPm4WJabbvpyaehQ0SrvVK2yfV79SytD9XDVxqiPvdrv2LK7DGSFo91TB2FgWanbJAZXg==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -436,13 +436,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.0.tgz", - "integrity": "sha512-6P0RuphkR+UuV7Avv7MU3hFoWaGcrgOdi8eTe1NwhMp2/GjUJoODBTRWzlHpZh6lFOaPmSvgxGlROa0Sg5Zbyg==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.1.tgz", + "integrity": "sha512-99b5e/Enoe8fKMLdSuwrfH/C0EIbpUWmeEKHmQlGZb8msY33qn1KlkFww0z26o5Omx7EVjzVDCWEfrfCDHfE7g==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/visitor-keys": "5.38.0", + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/visitor-keys": "5.38.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -463,15 +463,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.38.0.tgz", - "integrity": "sha512-6sdeYaBgk9Fh7N2unEXGz+D+som2QCQGPAf1SxrkEr+Z32gMreQ0rparXTNGRRfYUWk/JzbGdcM8NSSd6oqnTA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.38.1.tgz", + "integrity": "sha512-oIuUiVxPBsndrN81oP8tXnFa/+EcZ03qLqPDfSZ5xIJVm7A9V0rlkQwwBOAGtrdN70ZKDlKv+l1BeT4eSFxwXA==", "dev": true, "dependencies": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/typescript-estree": "5.38.0", + "@typescript-eslint/scope-manager": "5.38.1", + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/typescript-estree": "5.38.1", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" }, @@ -487,12 +487,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.0.tgz", - "integrity": "sha512-MxnrdIyArnTi+XyFLR+kt/uNAcdOnmT+879os7qDRI+EYySR4crXJq9BXPfRzzLGq0wgxkwidrCJ9WCAoacm1w==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.1.tgz", + "integrity": "sha512-bSHr1rRxXt54+j2n4k54p4fj8AHJ49VDWtjpImOpzQj4qjAiOpPni+V1Tyajh19Api1i844F757cur8wH3YvOA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.38.0", + "@typescript-eslint/types": "5.38.1", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -896,9 +896,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.262", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.262.tgz", - "integrity": "sha512-Ckn5haqmGh/xS8IbcgK3dnwAVnhDyo/WQnklWn6yaMucYTq7NNxwlGE8ElzEOnonzRLzUCo2Ot3vUb2GYUF2Hw==", + "version": "1.4.264", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.264.tgz", + "integrity": "sha512-AZ6ZRkucHOQT8wke50MktxtmcWZr67kE17X/nAXFf62NIdMdgY6xfsaJD5Szoy84lnkuPWH+4tTNE3s2+bPCiw==", "dev": true }, "node_modules/emoji-regex": { @@ -3302,20 +3302,20 @@ } }, "@types/node": { - "version": "16.11.60", - "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.60.tgz", - "integrity": "sha512-kYIYa1D1L+HDv5M5RXQeEu1o0FKA6yedZIoyugm/MBPROkLpX4L7HRxMrPVyo8bnvjpW/wDlqFNGzXNMb7AdRw==", + "version": "16.11.62", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.62.tgz", + "integrity": "sha512-K/ggecSdwAAy2NUW4WKmF4Rc03GKbsfP+k326UWgckoS+Rzd2PaWbjk76dSmqdLQvLTJAO9axiTUJ6488mFsYQ==", "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.0.tgz", - "integrity": "sha512-GgHi/GNuUbTOeoJiEANi0oI6fF3gBQc3bGFYj40nnAPCbhrtEDf2rjBmefFadweBmO1Du1YovHeDP2h5JLhtTQ==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.38.1.tgz", + "integrity": "sha512-ky7EFzPhqz3XlhS7vPOoMDaQnQMn+9o5ICR9CPr/6bw8HrFkzhMSxuA3gRfiJVvs7geYrSeawGJjZoZQKCOglQ==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/type-utils": "5.38.0", - "@typescript-eslint/utils": "5.38.0", + "@typescript-eslint/scope-manager": "5.38.1", + "@typescript-eslint/type-utils": "5.38.1", + "@typescript-eslint/utils": "5.38.1", "debug": "^4.3.4", "ignore": "^5.2.0", "regexpp": "^3.2.0", @@ -3324,53 +3324,53 @@ } }, "@typescript-eslint/parser": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.38.0.tgz", - "integrity": "sha512-/F63giJGLDr0ms1Cr8utDAxP2SPiglaD6V+pCOcG35P2jCqdfR7uuEhz1GIC3oy4hkUF8xA1XSXmd9hOh/a5EA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.38.1.tgz", + "integrity": "sha512-LDqxZBVFFQnQRz9rUZJhLmox+Ep5kdUmLatLQnCRR6523YV+XhRjfYzStQ4MheFA8kMAfUlclHSbu+RKdRwQKw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/typescript-estree": "5.38.0", + "@typescript-eslint/scope-manager": "5.38.1", + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/typescript-estree": "5.38.1", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.38.0.tgz", - "integrity": "sha512-ByhHIuNyKD9giwkkLqzezZ9y5bALW8VNY6xXcP+VxoH4JBDKjU5WNnsiD4HJdglHECdV+lyaxhvQjTUbRboiTA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.38.1.tgz", + "integrity": "sha512-BfRDq5RidVU3RbqApKmS7RFMtkyWMM50qWnDAkKgQiezRtLKsoyRKIvz1Ok5ilRWeD9IuHvaidaLxvGx/2eqTQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/visitor-keys": "5.38.0" + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/visitor-keys": "5.38.1" } }, "@typescript-eslint/type-utils": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.38.0.tgz", - "integrity": "sha512-iZq5USgybUcj/lfnbuelJ0j3K9dbs1I3RICAJY9NZZpDgBYXmuUlYQGzftpQA9wC8cKgtS6DASTvF3HrXwwozA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.38.1.tgz", + "integrity": "sha512-UU3j43TM66gYtzo15ivK2ZFoDFKKP0k03MItzLdq0zV92CeGCXRfXlfQX5ILdd4/DSpHkSjIgLLLh1NtkOJOAw==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.38.0", - "@typescript-eslint/utils": "5.38.0", + "@typescript-eslint/typescript-estree": "5.38.1", + "@typescript-eslint/utils": "5.38.1", "debug": "^4.3.4", "tsutils": "^3.21.0" } }, "@typescript-eslint/types": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.38.0.tgz", - "integrity": "sha512-HHu4yMjJ7i3Cb+8NUuRCdOGu2VMkfmKyIJsOr9PfkBVYLYrtMCK/Ap50Rpov+iKpxDTfnqvDbuPLgBE5FwUNfA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.38.1.tgz", + "integrity": "sha512-QTW1iHq1Tffp9lNfbfPm4WJabbvpyaehQ0SrvVK2yfV79SytD9XDVxqiPvdrv2LK7DGSFo91TB2FgWanbJAZXg==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.0.tgz", - "integrity": "sha512-6P0RuphkR+UuV7Avv7MU3hFoWaGcrgOdi8eTe1NwhMp2/GjUJoODBTRWzlHpZh6lFOaPmSvgxGlROa0Sg5Zbyg==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.38.1.tgz", + "integrity": "sha512-99b5e/Enoe8fKMLdSuwrfH/C0EIbpUWmeEKHmQlGZb8msY33qn1KlkFww0z26o5Omx7EVjzVDCWEfrfCDHfE7g==", "dev": true, "requires": { - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/visitor-keys": "5.38.0", + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/visitor-keys": "5.38.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -3379,26 +3379,26 @@ } }, "@typescript-eslint/utils": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.38.0.tgz", - "integrity": "sha512-6sdeYaBgk9Fh7N2unEXGz+D+som2QCQGPAf1SxrkEr+Z32gMreQ0rparXTNGRRfYUWk/JzbGdcM8NSSd6oqnTA==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.38.1.tgz", + "integrity": "sha512-oIuUiVxPBsndrN81oP8tXnFa/+EcZ03qLqPDfSZ5xIJVm7A9V0rlkQwwBOAGtrdN70ZKDlKv+l1BeT4eSFxwXA==", "dev": true, "requires": { "@types/json-schema": "^7.0.9", - "@typescript-eslint/scope-manager": "5.38.0", - "@typescript-eslint/types": "5.38.0", - "@typescript-eslint/typescript-estree": "5.38.0", + "@typescript-eslint/scope-manager": "5.38.1", + "@typescript-eslint/types": "5.38.1", + "@typescript-eslint/typescript-estree": "5.38.1", "eslint-scope": "^5.1.1", "eslint-utils": "^3.0.0" } }, "@typescript-eslint/visitor-keys": { - "version": "5.38.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.0.tgz", - "integrity": "sha512-MxnrdIyArnTi+XyFLR+kt/uNAcdOnmT+879os7qDRI+EYySR4crXJq9BXPfRzzLGq0wgxkwidrCJ9WCAoacm1w==", + "version": "5.38.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.38.1.tgz", + "integrity": "sha512-bSHr1rRxXt54+j2n4k54p4fj8AHJ49VDWtjpImOpzQj4qjAiOpPni+V1Tyajh19Api1i844F757cur8wH3YvOA==", "dev": true, "requires": { - "@typescript-eslint/types": "5.38.0", + "@typescript-eslint/types": "5.38.1", "eslint-visitor-keys": "^3.3.0" } }, @@ -3678,9 +3678,9 @@ } }, "electron-to-chromium": { - "version": "1.4.262", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.262.tgz", - "integrity": "sha512-Ckn5haqmGh/xS8IbcgK3dnwAVnhDyo/WQnklWn6yaMucYTq7NNxwlGE8ElzEOnonzRLzUCo2Ot3vUb2GYUF2Hw==", + "version": "1.4.264", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.264.tgz", + "integrity": "sha512-AZ6ZRkucHOQT8wke50MktxtmcWZr67kE17X/nAXFf62NIdMdgY6xfsaJD5Szoy84lnkuPWH+4tTNE3s2+bPCiw==", "dev": true }, "emoji-regex": { From 0e85978d975b71b3bb74e19ec5692e02ec4a53d2 Mon Sep 17 00:00:00 2001 From: Pascal Jufer Date: Sat, 1 Oct 2022 13:14:28 +0200 Subject: [PATCH 6/8] Add FAQ section with solution for required matrix jobs (#283) --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/README.md b/README.md index 8b4ff8f..359c40f 100644 --- a/README.md +++ b/README.md @@ -404,6 +404,33 @@ stateDiagram-v2 Skipped_No --> Dont_Skip: (Because changed files needs to be "tested") ``` +## Frequently Asked Questions + +### Skip Check in Required Matrix Job + +Discussed in https://github.com/fkirc/skip-duplicate-actions/issues/44. + +If you have matrix jobs that are registered as required status checks and the matrix runs conditionally based on the skip check, you might run into the problem that the pull request remains in a unmergable state forever because the jobs are not executed at all and thus not reported as skipped (`Expected - Waiting for status to be reported`). + +There are several approaches to circumvent this problem: + +- Define the condition (`if`) in each step in the matrix job instead of a single condition on the job level: https://github.com/fkirc/skip-duplicate-actions/issues/44 +- If you want the check to be considered successful only if all jobs in the matrix were successful, you can add a subsequent job whose only task is to report the final status of the matrix. Then you can register this final job as a required status check: + ```yaml + result: + name: Result + if: needs.pre_job.outputs.should_skip != 'true' && always() + runs-on: ubuntu-latest + needs: + - pre_job + - example-matrix-job + steps: + - name: Mark result as failed + if: needs.example-matrix-job.result != 'success' + run: exit 1 + ``` +- Define an opposite workflow, as offically suggested by GitHub: [Handling skipped but required checks](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/troubleshooting-required-status-checks#handling-skipped-but-required-checks) + ## Maintainers - [@paescuj](https://github.com/paescuj) From ae7e57446110955ed161a1933a6d894b49c9254b Mon Sep 17 00:00:00 2001 From: Pascal Jufer Date: Sat, 1 Oct 2022 13:17:15 +0200 Subject: [PATCH 7/8] Transform to a real question (#284) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 359c40f..417047c 100644 --- a/README.md +++ b/README.md @@ -406,7 +406,7 @@ stateDiagram-v2 ## Frequently Asked Questions -### Skip Check in Required Matrix Job +### How to Use Skip Check With Required Matrix Jobs? Discussed in https://github.com/fkirc/skip-duplicate-actions/issues/44. From f11521568414503656a5af807dc3018c012552c4 Mon Sep 17 00:00:00 2001 From: Pascal Jufer Date: Sat, 1 Oct 2022 13:25:24 +0200 Subject: [PATCH 8/8] Update dependencies & rebuild (#285) --- dist/index.js | 63 +++++++++++++++++++++-------------- package-lock.json | 84 +++++++++++++++++++++++------------------------ 2 files changed, 81 insertions(+), 66 deletions(-) diff --git a/dist/index.js b/dist/index.js index 4a3c215..26dcf56 100644 --- a/dist/index.js +++ b/dist/index.js @@ -673,7 +673,6 @@ const file_command_1 = __nccwpck_require__(717); const utils_1 = __nccwpck_require__(5278); const os = __importStar(__nccwpck_require__(2037)); const path = __importStar(__nccwpck_require__(1017)); -const uuid_1 = __nccwpck_require__(5840); const oidc_utils_1 = __nccwpck_require__(8041); /** * The code to exit an action @@ -703,20 +702,9 @@ function exportVariable(name, val) { process.env[name] = convertedVal; const filePath = process.env['GITHUB_ENV'] || ''; if (filePath) { - const delimiter = `ghadelimiter_${uuid_1.v4()}`; - // These should realistically never happen, but just in case someone finds a way to exploit uuid generation let's not allow keys or values that contain the delimiter. - if (name.includes(delimiter)) { - throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); - } - if (convertedVal.includes(delimiter)) { - throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); - } - const commandValue = `${name}<<${delimiter}${os.EOL}${convertedVal}${os.EOL}${delimiter}`; - file_command_1.issueCommand('ENV', commandValue); - } - else { - command_1.issueCommand('set-env', { name }, convertedVal); + return file_command_1.issueFileCommand('ENV', file_command_1.prepareKeyValueMessage(name, val)); } + command_1.issueCommand('set-env', { name }, convertedVal); } exports.exportVariable = exportVariable; /** @@ -734,7 +722,7 @@ exports.setSecret = setSecret; function addPath(inputPath) { const filePath = process.env['GITHUB_PATH'] || ''; if (filePath) { - file_command_1.issueCommand('PATH', inputPath); + file_command_1.issueFileCommand('PATH', inputPath); } else { command_1.issueCommand('add-path', {}, inputPath); @@ -774,7 +762,10 @@ function getMultilineInput(name, options) { const inputs = getInput(name, options) .split('\n') .filter(x => x !== ''); - return inputs; + if (options && options.trimWhitespace === false) { + return inputs; + } + return inputs.map(input => input.trim()); } exports.getMultilineInput = getMultilineInput; /** @@ -807,8 +798,12 @@ exports.getBooleanInput = getBooleanInput; */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function setOutput(name, value) { + const filePath = process.env['GITHUB_OUTPUT'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('OUTPUT', file_command_1.prepareKeyValueMessage(name, value)); + } process.stdout.write(os.EOL); - command_1.issueCommand('set-output', { name }, value); + command_1.issueCommand('set-output', { name }, utils_1.toCommandValue(value)); } exports.setOutput = setOutput; /** @@ -937,7 +932,11 @@ exports.group = group; */ // eslint-disable-next-line @typescript-eslint/no-explicit-any function saveState(name, value) { - command_1.issueCommand('save-state', { name }, value); + const filePath = process.env['GITHUB_STATE'] || ''; + if (filePath) { + return file_command_1.issueFileCommand('STATE', file_command_1.prepareKeyValueMessage(name, value)); + } + command_1.issueCommand('save-state', { name }, utils_1.toCommandValue(value)); } exports.saveState = saveState; /** @@ -1003,13 +1002,14 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.issueCommand = void 0; +exports.prepareKeyValueMessage = exports.issueFileCommand = void 0; // We use any as a valid input type /* eslint-disable @typescript-eslint/no-explicit-any */ const fs = __importStar(__nccwpck_require__(7147)); const os = __importStar(__nccwpck_require__(2037)); +const uuid_1 = __nccwpck_require__(5840); const utils_1 = __nccwpck_require__(5278); -function issueCommand(command, message) { +function issueFileCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; if (!filePath) { throw new Error(`Unable to find environment variable for file command ${command}`); @@ -1021,7 +1021,22 @@ function issueCommand(command, message) { encoding: 'utf8' }); } -exports.issueCommand = issueCommand; +exports.issueFileCommand = issueFileCommand; +function prepareKeyValueMessage(key, value) { + const delimiter = `ghadelimiter_${uuid_1.v4()}`; + const convertedValue = utils_1.toCommandValue(value); + // These should realistically never happen, but just in case someone finds a + // way to exploit uuid generation let's not allow keys or values that contain + // the delimiter. + if (key.includes(delimiter)) { + throw new Error(`Unexpected input: name should not contain the delimiter "${delimiter}"`); + } + if (convertedValue.includes(delimiter)) { + throw new Error(`Unexpected input: value should not contain the delimiter "${delimiter}"`); + } + return `${key}<<${delimiter}${os.EOL}${convertedValue}${os.EOL}${delimiter}`; +} +exports.prepareKeyValueMessage = prepareKeyValueMessage; //# sourceMappingURL=file-command.js.map /***/ }), @@ -1692,7 +1707,7 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.getOctokitOptions = exports.GitHub = exports.context = void 0; +exports.getOctokitOptions = exports.GitHub = exports.defaults = exports.context = void 0; const Context = __importStar(__nccwpck_require__(4087)); const Utils = __importStar(__nccwpck_require__(7914)); // octokit + plugins @@ -1701,13 +1716,13 @@ const plugin_rest_endpoint_methods_1 = __nccwpck_require__(3044); const plugin_paginate_rest_1 = __nccwpck_require__(4193); exports.context = new Context.Context(); const baseUrl = Utils.getApiBaseUrl(); -const defaults = { +exports.defaults = { baseUrl, request: { agent: Utils.getProxyAgent(baseUrl) } }; -exports.GitHub = core_1.Octokit.plugin(plugin_rest_endpoint_methods_1.restEndpointMethods, plugin_paginate_rest_1.paginateRest).defaults(defaults); +exports.GitHub = core_1.Octokit.plugin(plugin_rest_endpoint_methods_1.restEndpointMethods, plugin_paginate_rest_1.paginateRest).defaults(exports.defaults); /** * Convience function to correctly format Octokit Options to pass into the constructor. * diff --git a/package-lock.json b/package-lock.json index e7d19e8..423e43f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,18 +26,18 @@ } }, "node_modules/@actions/core": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", - "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz", + "integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==", "dependencies": { "@actions/http-client": "^2.0.1", "uuid": "^8.3.2" } }, "node_modules/@actions/github": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz", - "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz", + "integrity": "sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==", "dependencies": { "@actions/http-client": "^2.0.1", "@octokit/core": "^3.6.0", @@ -102,9 +102,9 @@ } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz", - "integrity": "sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==", + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", + "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", "dev": true, "dependencies": { "@humanwhocodes/object-schema": "^1.2.1", @@ -741,9 +741,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001412", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001412.tgz", - "integrity": "sha512-+TeEIee1gS5bYOiuf+PS/kp2mrXic37Hl66VY6EAfxasIk5fELTktK2oOezYed12H8w7jt3s512PpulQidPjwA==", + "version": "1.0.30001414", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001414.tgz", + "integrity": "sha512-t55jfSaWjCdocnFdKQoO+d2ct9C59UZg4dY3OnUlSZ447r8pUtIKdp0hpAzrGFultmTC+Us+KpKi4GZl/LXlFg==", "dev": true, "funding": [ { @@ -896,9 +896,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.264", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.264.tgz", - "integrity": "sha512-AZ6ZRkucHOQT8wke50MktxtmcWZr67kE17X/nAXFf62NIdMdgY6xfsaJD5Szoy84lnkuPWH+4tTNE3s2+bPCiw==", + "version": "1.4.270", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.270.tgz", + "integrity": "sha512-KNhIzgLiJmDDC444dj9vEOpZEgsV96ult9Iff98Vanumn+ShJHd5se8aX6KeVxdc0YQeqdrezBZv89rleDbvSg==", "dev": true }, "node_modules/emoji-regex": { @@ -2077,9 +2077,9 @@ "dev": true }, "node_modules/js-sdsl": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz", - "integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", + "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", "dev": true }, "node_modules/js-yaml": { @@ -2900,9 +2900,9 @@ } }, "node_modules/typescript": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -3055,18 +3055,18 @@ }, "dependencies": { "@actions/core": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.9.1.tgz", - "integrity": "sha512-5ad+U2YGrmmiw6du20AQW5XuWo7UKN2052FjSV7MX+Wfjf8sCqcsZe62NfgHys4QI4/Y+vQvLKYL8jWtA1ZBTA==", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.0.tgz", + "integrity": "sha512-2aZDDa3zrrZbP5ZYg159sNoLRb61nQ7awl5pSvIq5Qpj81vwDzdMRKzkWJGJuwVvWpvZKx7vspJALyvaaIQyug==", "requires": { "@actions/http-client": "^2.0.1", "uuid": "^8.3.2" } }, "@actions/github": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.0.tgz", - "integrity": "sha512-tuI80F7JQIhg77ZTTgUAPpVD7ZnP9oHSPN8xw7LOwtA4vEMbAjWJNbmLBfV7xua7r016GyjzWLuec5cs8f/a8A==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@actions/github/-/github-5.1.1.tgz", + "integrity": "sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==", "requires": { "@actions/http-client": "^2.0.1", "@octokit/core": "^3.6.0", @@ -3119,9 +3119,9 @@ } }, "@humanwhocodes/config-array": { - "version": "0.10.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.5.tgz", - "integrity": "sha512-XVVDtp+dVvRxMoxSiSfasYaG02VEe1qH5cKgMQJWhol6HwzbcqoCMJi8dAGoYAO57jhUyhI6cWuRiTcRaDaYug==", + "version": "0.10.7", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.10.7.tgz", + "integrity": "sha512-MDl6D6sBsaV452/QSdX+4CXIjZhIcI0PELsxUjk4U828yd58vk3bTIvk/6w5FY+4hIy9sLW0sfrV7K7Kc++j/w==", "dev": true, "requires": { "@humanwhocodes/object-schema": "^1.2.1", @@ -3570,9 +3570,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001412", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001412.tgz", - "integrity": "sha512-+TeEIee1gS5bYOiuf+PS/kp2mrXic37Hl66VY6EAfxasIk5fELTktK2oOezYed12H8w7jt3s512PpulQidPjwA==", + "version": "1.0.30001414", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001414.tgz", + "integrity": "sha512-t55jfSaWjCdocnFdKQoO+d2ct9C59UZg4dY3OnUlSZ447r8pUtIKdp0hpAzrGFultmTC+Us+KpKi4GZl/LXlFg==", "dev": true }, "chalk": { @@ -3678,9 +3678,9 @@ } }, "electron-to-chromium": { - "version": "1.4.264", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.264.tgz", - "integrity": "sha512-AZ6ZRkucHOQT8wke50MktxtmcWZr67kE17X/nAXFf62NIdMdgY6xfsaJD5Szoy84lnkuPWH+4tTNE3s2+bPCiw==", + "version": "1.4.270", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.270.tgz", + "integrity": "sha512-KNhIzgLiJmDDC444dj9vEOpZEgsV96ult9Iff98Vanumn+ShJHd5se8aX6KeVxdc0YQeqdrezBZv89rleDbvSg==", "dev": true }, "emoji-regex": { @@ -4555,9 +4555,9 @@ "dev": true }, "js-sdsl": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.4.tgz", - "integrity": "sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", + "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", "dev": true }, "js-yaml": { @@ -5133,9 +5133,9 @@ "dev": true }, "typescript": { - "version": "4.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.3.tgz", - "integrity": "sha512-goMHfm00nWPa8UvR/CPSvykqf6dVV8x/dp0c5mFTMTIu0u0FlGWRioyy7Nn0PGAdHxpJZnuO/ut+PpQ8UiHAig==", + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.8.4.tgz", + "integrity": "sha512-QCh+85mCy+h0IGff8r5XWzOVSbBO+KfeYrMQh7NJ58QujwcE22u+NUSmUxqF+un70P9GXKxa2HCNiTTMJknyjQ==", "dev": true }, "unbox-primitive": {