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:
Martijn Pieters 2023-03-30 16:05:10 +01:00
parent 36d245c808
commit 454e5d7e69
No known key found for this signature in database
6 changed files with 1523 additions and 1323 deletions

View file

@ -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

View file

@ -8,6 +8,7 @@ on:
jobs: jobs:
test-return: test-return:
name: 'Integration test: return'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -18,26 +19,34 @@ jobs:
result-encoding: string result-encoding: string
input-value: output input-value: output
- run: | - run: |
if [[ "${{steps.output-set.outputs.result}}" != "output" ]]; then echo "- Validating output is produced"
expected="output"
if [[ "${{steps.output-set.outputs.result}}" != "$expected" ]]; then
echo $'::error::\u274C' "Expected '$expected', got ${{steps.output-set.outputs.result}}"
exit 1 exit 1
fi fi
echo $'\u2705 Test passed' | tee -a $GITHUB_STEP_SUMMARY
test-relative-require: test-relative-require:
name: 'Integration test: relative-path require'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
- id: output-set - id: relative-require
uses: ./ uses: ./
with: with:
script: return require('./package.json').name script: return require('./package.json').name
result-encoding: string result-encoding: string
input-value: output
- run: | - run: |
if [[ "${{steps.output-set.outputs.result}}" != "github-script" ]]; then echo "- Validating relative require output"
if [[ "${{steps.relative-require.outputs.result}}" != "github-script" ]]; then
echo $'::error::\u274C' "Expected '$expected', got ${{steps.relative-require.outputs.result}}"
exit 1 exit 1
fi fi
echo $'\u2705 Test passed' | tee -a $GITHUB_STEP_SUMMARY
test-npm-require: test-npm-require:
name: 'Integration test: npm package require'
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -47,13 +56,196 @@ jobs:
key: ${{runner.os}}-npm-${{hashFiles('**/package-lock.json')}} key: ${{runner.os}}-npm-${{hashFiles('**/package-lock.json')}}
restore-keys: ${{runner.os}}-npm- restore-keys: ${{runner.os}}-npm-
- run: npm ci - run: npm ci
- id: output-set - id: npm-require
uses: ./ uses: ./
with: with:
script: return require('@actions/core/package.json').name script: return require('@actions/core/package.json').name
result-encoding: string result-encoding: string
input-value: output
- run: | - run: |
if [[ "${{steps.output-set.outputs.result}}" != "@actions/core" ]]; then echo "- Validating npm require output"
expected="@actions/core"
if [[ "${{steps.npm-require.outputs.result}}" != "$expected" ]]; then
echo $'::error::\u274C' "Expected '$expected', got ${{steps.npm-require.outputs.result}}"
exit 1 exit 1
fi fi
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

2616
dist/index.js vendored

File diff suppressed because it is too large Load diff

View file

@ -6,10 +6,10 @@ import * as glob from '@actions/glob'
import * as io from '@actions/io' import * as io from '@actions/io'
import {retry} from '@octokit/plugin-retry' import {retry} from '@octokit/plugin-retry'
import {RequestRequestOptions} from '@octokit/types' import {RequestRequestOptions} from '@octokit/types'
import fetch from 'node-fetch'
import {callAsyncFunction} from './async-function' import {callAsyncFunction} from './async-function'
import {getRetryOptions, parseNumberArray, RetryOptions} from './retry-options' import {getRetryOptions, parseNumberArray, RetryOptions} from './retry-options'
import {wrapRequire} from './wrap-require' import {wrapRequire} from './wrap-require'
import fetch from 'node-fetch'
process.on('unhandledRejection', handleError) process.on('unhandledRejection', handleError)
main().catch(handleError) main().catch(handleError)
@ -24,7 +24,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'))
@ -37,11 +37,12 @@ async function main(): Promise<void> {
defaultGitHubOptions defaultGitHubOptions
) )
const opts: Options = {} const opts: Options = {
if (debug === 'true') opts.log = console retry: retryOpts
if (userAgent != null) opts.userAgent = userAgent }
if (previews != null) opts.previews = previews.split(',') if (debug) opts.log = console
if (retryOpts) opts.retry = retryOpts if (userAgent) opts.userAgent = userAgent
if (previews) opts.previews = previews.split(',')
if (requestOpts) opts.request = requestOpts if (requestOpts) opts.request = requestOpts
const github = getOctokit(token, opts, retry) const github = getOctokit(token, opts, retry)

View file

@ -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
View file

@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"exclude": []
}