mirror of
https://github.com/actions/github-script.git
synced 2025-12-08 08:06:23 +00:00
Fix null handling, covered by integration tests
`core.getInput()` always returns a string, so testing for 'not null' is always true. This then leads to previews set to an array with a single empty string, breaking accept-header output. Updated eslint rules should help avoid this issue in future, and new integration tests verify that the github client configuration now reflects the intended configuration options.
This commit is contained in:
@@ -6,8 +6,11 @@ extends:
|
|||||||
- plugin:@typescript-eslint/eslint-recommended
|
- plugin:@typescript-eslint/eslint-recommended
|
||||||
- plugin:@typescript-eslint/recommended
|
- plugin:@typescript-eslint/recommended
|
||||||
- prettier/@typescript-eslint
|
- prettier/@typescript-eslint
|
||||||
|
parserOptions:
|
||||||
|
project: ['tsconfig.eslint.json']
|
||||||
rules:
|
rules:
|
||||||
# '@typescript-eslint/explicit-function-return-type': 0
|
# '@typescript-eslint/explicit-function-return-type': 0
|
||||||
'@typescript-eslint/no-use-before-define':
|
'@typescript-eslint/no-use-before-define':
|
||||||
- 2
|
- 2
|
||||||
- functions: false
|
- functions: false
|
||||||
|
'@typescript-eslint/no-unnecessary-condition': error
|
||||||
|
|||||||
180
.github/workflows/integration.yml
vendored
180
.github/workflows/integration.yml
vendored
@@ -69,3 +69,183 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo $'\u2705 Test passed' | tee -a $GITHUB_STEP_SUMMARY
|
echo $'\u2705 Test passed' | tee -a $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
test-previews:
|
||||||
|
name: 'Integration test: previews option'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.npm
|
||||||
|
key: ${{runner.os}}-npm-${{hashFiles('**/package-lock.json')}}
|
||||||
|
restore-keys: ${{runner.os}}-npm-
|
||||||
|
- run: npm ci
|
||||||
|
- id: previews-default
|
||||||
|
name: Default previews not set
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const endpoint = github.request.endpoint
|
||||||
|
return endpoint({}).headers.accept
|
||||||
|
result-encoding: string
|
||||||
|
- id: previews-set-single
|
||||||
|
name: Previews set to a single value
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
previews: foo
|
||||||
|
script: |
|
||||||
|
const endpoint = github.request.endpoint
|
||||||
|
return endpoint({}).headers.accept
|
||||||
|
result-encoding: string
|
||||||
|
- id: previews-set-multiple
|
||||||
|
name: Previews set to comma-separated list
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
previews: foo,bar,baz
|
||||||
|
script: |
|
||||||
|
const endpoint = github.request.endpoint
|
||||||
|
return endpoint({}).headers.accept
|
||||||
|
result-encoding: string
|
||||||
|
- run: |
|
||||||
|
echo "- Validating previews default"
|
||||||
|
expected="application/vnd.github.v3+json"
|
||||||
|
if [[ "${{steps.previews-default.outputs.result}}" != $expected ]]; then
|
||||||
|
echo $'::error::\u274C' "Expected '$expected', got ${{steps.previews-default.outputs.result}}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "- Validating previews set to a single value"
|
||||||
|
expected="application/vnd.github.foo-preview+json"
|
||||||
|
if [[ "${{steps.previews-set-single.outputs.result}}" != $expected ]]; then
|
||||||
|
echo $'::error::\u274C' "Expected '$expected', got ${{steps.previews-set-single.outputs.result}}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "- Validating previews set to multiple values"
|
||||||
|
expected="application/vnd.github.foo-preview+json,application/vnd.github.bar-preview+json,application/vnd.github.baz-preview+json"
|
||||||
|
if [[ "${{steps.previews-set-multiple.outputs.result}}" != $expected ]]; then
|
||||||
|
echo $'::error::\u274C' "Expected '$expected', got ${{steps.previews-set-multiple.outputs.result}}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo $'\u2705 Test passed' | tee -a $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
test-user-agent:
|
||||||
|
name: 'Integration test: user-agent option'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.npm
|
||||||
|
key: ${{runner.os}}-npm-${{hashFiles('**/package-lock.json')}}
|
||||||
|
restore-keys: ${{runner.os}}-npm-
|
||||||
|
- run: npm ci
|
||||||
|
- id: user-agent-default
|
||||||
|
name: Default user-agent not set
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const endpoint = github.request.endpoint
|
||||||
|
return endpoint({}).headers['user-agent']
|
||||||
|
result-encoding: string
|
||||||
|
- id: user-agent-set
|
||||||
|
name: User-agent set
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
user-agent: foobar
|
||||||
|
script: |
|
||||||
|
const endpoint = github.request.endpoint
|
||||||
|
return endpoint({}).headers['user-agent']
|
||||||
|
result-encoding: string
|
||||||
|
- id: user-agent-empty
|
||||||
|
name: User-agent set to an empty string
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
user-agent: ''
|
||||||
|
script: |
|
||||||
|
const endpoint = github.request.endpoint
|
||||||
|
return endpoint({}).headers['user-agent']
|
||||||
|
result-encoding: string
|
||||||
|
- run: |
|
||||||
|
echo "- Validating user-agent default"
|
||||||
|
expected="actions/github-script octokit-core.js/"
|
||||||
|
if [[ "${{steps.user-agent-default.outputs.result}}" != "$expected"* ]]; then
|
||||||
|
echo $'::error::\u274C' "Expected user-agent to start with '$expected', got ${{steps.user-agent-default.outputs.result}}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "- Validating user-agent set to a value"
|
||||||
|
expected="foobar octokit-core.js/"
|
||||||
|
if [[ "${{steps.user-agent-set.outputs.result}}" != "$expected"* ]]; then
|
||||||
|
echo $'::error::\u274C' "Expected user-agent to start with '$expected', got ${{steps.user-agent-set.outputs.result}}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "- Validating user-agent set to an empty string"
|
||||||
|
expected="octokit-core.js/"
|
||||||
|
if [[ "${{steps.user-agent-empty.outputs.result}}" != "$expected"* ]]; then
|
||||||
|
echo $'::error::\u274C' "Expected user-agent to start with '$expected', got ${{steps.user-agent-empty.outputs.result}}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo $'\u2705 Test passed' | tee -a $GITHUB_STEP_SUMMARY
|
||||||
|
|
||||||
|
test-debug:
|
||||||
|
name: 'Integration test: debug option'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.npm
|
||||||
|
key: ${{runner.os}}-npm-${{hashFiles('**/package-lock.json')}}
|
||||||
|
restore-keys: ${{runner.os}}-npm-
|
||||||
|
- run: npm ci
|
||||||
|
- id: debug-default
|
||||||
|
name: Default debug not set
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const log = github.log
|
||||||
|
return {
|
||||||
|
debug: log.debug === console.debug,
|
||||||
|
info: log.info === console.info
|
||||||
|
}
|
||||||
|
- id: debug-true
|
||||||
|
name: Debug set to true
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
debug: true
|
||||||
|
script: |
|
||||||
|
const log = github.log
|
||||||
|
return {
|
||||||
|
debug: log.debug === console.debug,
|
||||||
|
info: log.info === console.info
|
||||||
|
}
|
||||||
|
- id: debug-false
|
||||||
|
name: Debug set to false
|
||||||
|
uses: ./
|
||||||
|
with:
|
||||||
|
debug: false
|
||||||
|
script: |
|
||||||
|
const log = github.log
|
||||||
|
return {
|
||||||
|
debug: log.debug === console.debug,
|
||||||
|
info: log.info === console.info
|
||||||
|
}
|
||||||
|
- run: |
|
||||||
|
echo "- Validating debug default"
|
||||||
|
expected='{debug:false,info:false}'
|
||||||
|
if [[ "${{steps.debug-default.outputs.result}}" != "$expected" ]]; then
|
||||||
|
echo $'::error::\u274C' "Expected '$expected', got ${{steps.debug-default.outputs.result}}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "- Validating debug set to true"
|
||||||
|
expected='{debug:true,info:true}'
|
||||||
|
if [[ "${{steps.debug-true.outputs.result}}" != "$expected" ]]; then
|
||||||
|
echo $'::error::\u274C' "Expected '$expected', got ${{steps.debug-true.outputs.result}}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "- Validating debug set to false"
|
||||||
|
expected='{debug:false,info:false}'
|
||||||
|
if [[ "${{steps.debug-false.outputs.result}}" != "$expected" ]]; then
|
||||||
|
echo $'::error::\u274C' "Expected '$expected', got ${{steps.debug-false.outputs.result}}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo $'\u2705 Test passed' | tee -a $GITHUB_STEP_SUMMARY
|
||||||
|
|||||||
28
dist/index.js
vendored
28
dist/index.js
vendored
@@ -15134,6 +15134,9 @@ var io = __nccwpck_require__(7436);
|
|||||||
var dist_node = __nccwpck_require__(8883);
|
var dist_node = __nccwpck_require__(8883);
|
||||||
// EXTERNAL MODULE: ./node_modules/@octokit/plugin-retry/dist-node/index.js
|
// EXTERNAL MODULE: ./node_modules/@octokit/plugin-retry/dist-node/index.js
|
||||||
var plugin_retry_dist_node = __nccwpck_require__(6298);
|
var plugin_retry_dist_node = __nccwpck_require__(6298);
|
||||||
|
// EXTERNAL MODULE: ./node_modules/node-fetch/lib/index.js
|
||||||
|
var lib = __nccwpck_require__(467);
|
||||||
|
var lib_default = /*#__PURE__*/__nccwpck_require__.n(lib);
|
||||||
;// CONCATENATED MODULE: ./src/async-function.ts
|
;// CONCATENATED MODULE: ./src/async-function.ts
|
||||||
const AsyncFunction = Object.getPrototypeOf(async () => null).constructor;
|
const AsyncFunction = Object.getPrototypeOf(async () => null).constructor;
|
||||||
function callAsyncFunction(args, source) {
|
function callAsyncFunction(args, source) {
|
||||||
@@ -15161,7 +15164,7 @@ function getRetryOptions(retries, exemptStatusCodes, defaultOptions) {
|
|||||||
...defaultOptions.request,
|
...defaultOptions.request,
|
||||||
retries
|
retries
|
||||||
};
|
};
|
||||||
core.debug(`GitHub client configured with: (retries: ${requestOptions.retries}, retry-exempt-status-code: ${(_a = retryOptions === null || retryOptions === void 0 ? void 0 : retryOptions.doNotRetry) !== null && _a !== void 0 ? _a : 'octokit default: [400, 401, 403, 404, 422]'})`);
|
core.debug(`GitHub client configured with: (retries: ${requestOptions.retries}, retry-exempt-status-code: ${(_a = retryOptions.doNotRetry) !== null && _a !== void 0 ? _a : 'octokit default: [400, 401, 403, 404, 422]'})`);
|
||||||
return [retryOptions, requestOptions];
|
return [retryOptions, requestOptions];
|
||||||
}
|
}
|
||||||
function parseNumberArray(listString) {
|
function parseNumberArray(listString) {
|
||||||
@@ -15197,9 +15200,6 @@ const wrapRequire = new Proxy(require, {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// EXTERNAL MODULE: ./node_modules/node-fetch/lib/index.js
|
|
||||||
var lib = __nccwpck_require__(467);
|
|
||||||
var lib_default = /*#__PURE__*/__nccwpck_require__.n(lib);
|
|
||||||
;// CONCATENATED MODULE: ./src/main.ts
|
;// CONCATENATED MODULE: ./src/main.ts
|
||||||
|
|
||||||
|
|
||||||
@@ -15217,23 +15217,19 @@ process.on('unhandledRejection', handleError);
|
|||||||
main().catch(handleError);
|
main().catch(handleError);
|
||||||
async function main() {
|
async function main() {
|
||||||
const token = core.getInput('github-token', { required: true });
|
const token = core.getInput('github-token', { required: true });
|
||||||
const debug = core.getInput('debug');
|
const debug = core.getBooleanInput('debug');
|
||||||
const userAgent = core.getInput('user-agent');
|
const userAgent = core.getInput('user-agent');
|
||||||
const previews = core.getInput('previews');
|
const previews = core.getInput('previews');
|
||||||
const retries = parseInt(core.getInput('retries'));
|
const retries = parseInt(core.getInput('retries'));
|
||||||
const exemptStatusCodes = parseNumberArray(core.getInput('retry-exempt-status-codes'));
|
const exemptStatusCodes = parseNumberArray(core.getInput('retry-exempt-status-codes'));
|
||||||
const [retryOpts, requestOpts] = getRetryOptions(retries, exemptStatusCodes, utils.defaults);
|
const [retryOpts, requestOpts] = getRetryOptions(retries, exemptStatusCodes, utils.defaults);
|
||||||
const opts = {};
|
const opts = {
|
||||||
if (debug === 'true')
|
log: debug ? console : undefined,
|
||||||
opts.log = console;
|
userAgent: userAgent || undefined,
|
||||||
if (userAgent != null)
|
previews: previews ? previews.split(',') : undefined,
|
||||||
opts.userAgent = userAgent;
|
retry: retryOpts,
|
||||||
if (previews != null)
|
request: requestOpts
|
||||||
opts.previews = previews.split(',');
|
};
|
||||||
if (retryOpts)
|
|
||||||
opts.retry = retryOpts;
|
|
||||||
if (requestOpts)
|
|
||||||
opts.request = requestOpts;
|
|
||||||
const github = (0,lib_github.getOctokit)(token, opts, plugin_retry_dist_node/* retry */.XD, dist_node/* requestLog */.g);
|
const github = (0,lib_github.getOctokit)(token, opts, plugin_retry_dist_node/* retry */.XD, dist_node/* requestLog */.g);
|
||||||
const script = core.getInput('script', { required: true });
|
const script = core.getInput('script', { required: true });
|
||||||
// Using property/value shorthand on `require` (e.g. `{require}`) causes compilation errors.
|
// Using property/value shorthand on `require` (e.g. `{require}`) causes compilation errors.
|
||||||
|
|||||||
21
src/main.ts
21
src/main.ts
@@ -7,10 +7,10 @@ import * as io from '@actions/io'
|
|||||||
import {requestLog} from '@octokit/plugin-request-log'
|
import {requestLog} from '@octokit/plugin-request-log'
|
||||||
import {retry} from '@octokit/plugin-retry'
|
import {retry} from '@octokit/plugin-retry'
|
||||||
import {RequestRequestOptions} from '@octokit/types'
|
import {RequestRequestOptions} from '@octokit/types'
|
||||||
import {callAsyncFunction} from './async-function'
|
|
||||||
import {getRetryOptions, parseNumberArray, RetryOptions} from './retry-options'
|
|
||||||
import {wrapRequire} from './wrap-require'
|
|
||||||
import fetch from 'node-fetch'
|
import fetch from 'node-fetch'
|
||||||
|
import {callAsyncFunction} from './async-function'
|
||||||
|
import {RetryOptions, getRetryOptions, parseNumberArray} from './retry-options'
|
||||||
|
import {wrapRequire} from './wrap-require'
|
||||||
|
|
||||||
process.on('unhandledRejection', handleError)
|
process.on('unhandledRejection', handleError)
|
||||||
main().catch(handleError)
|
main().catch(handleError)
|
||||||
@@ -25,7 +25,7 @@ type Options = {
|
|||||||
|
|
||||||
async function main(): Promise<void> {
|
async function main(): Promise<void> {
|
||||||
const token = core.getInput('github-token', {required: true})
|
const token = core.getInput('github-token', {required: true})
|
||||||
const debug = core.getInput('debug')
|
const debug = core.getBooleanInput('debug')
|
||||||
const userAgent = core.getInput('user-agent')
|
const userAgent = core.getInput('user-agent')
|
||||||
const previews = core.getInput('previews')
|
const previews = core.getInput('previews')
|
||||||
const retries = parseInt(core.getInput('retries'))
|
const retries = parseInt(core.getInput('retries'))
|
||||||
@@ -38,12 +38,13 @@ async function main(): Promise<void> {
|
|||||||
defaultGitHubOptions
|
defaultGitHubOptions
|
||||||
)
|
)
|
||||||
|
|
||||||
const opts: Options = {}
|
const opts: Options = {
|
||||||
if (debug === 'true') opts.log = console
|
log: debug ? console : undefined,
|
||||||
if (userAgent != null) opts.userAgent = userAgent
|
userAgent: userAgent || undefined,
|
||||||
if (previews != null) opts.previews = previews.split(',')
|
previews: previews ? previews.split(',') : undefined,
|
||||||
if (retryOpts) opts.retry = retryOpts
|
retry: retryOpts,
|
||||||
if (requestOpts) opts.request = requestOpts
|
request: requestOpts
|
||||||
|
}
|
||||||
|
|
||||||
const github = getOctokit(token, opts, retry, requestLog)
|
const github = getOctokit(token, opts, retry, requestLog)
|
||||||
const script = core.getInput('script', {required: true})
|
const script = core.getInput('script', {required: true})
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export function getRetryOptions(
|
|||||||
`GitHub client configured with: (retries: ${
|
`GitHub client configured with: (retries: ${
|
||||||
requestOptions.retries
|
requestOptions.retries
|
||||||
}, retry-exempt-status-code: ${
|
}, retry-exempt-status-code: ${
|
||||||
retryOptions?.doNotRetry ?? 'octokit default: [400, 401, 403, 404, 422]'
|
retryOptions.doNotRetry ?? 'octokit default: [400, 401, 403, 404, 422]'
|
||||||
})`
|
})`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
4
tsconfig.eslint.json
Normal file
4
tsconfig.eslint.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"exclude": []
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user