diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 20e250e1..2c9b3ff1 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version-file: '.nvmrc' + node-version-file: '.node-version' registry-url: 'https://registry.npmjs.org' - name: Install Yarn diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 43897b00..3a3c0423 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -4,7 +4,6 @@ on: workflow_dispatch: schedule: - cron: 30 15 * * 0-6 - push: tags-ignore: - '*.*' diff --git a/.github/workflows/production.yml b/.github/workflows/production.yml index eaf83567..aceede5f 100644 --- a/.github/workflows/production.yml +++ b/.github/workflows/production.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/setup-node@v4 with: - node-version-file: '.nvmrc' + node-version-file: '.node-version' registry-url: 'https://registry.npmjs.org' - name: Install Yarn diff --git a/.github/workflows/version.yml b/.github/workflows/version.yml index 23132948..abff8140 100644 --- a/.github/workflows/version.yml +++ b/.github/workflows/version.yml @@ -29,7 +29,7 @@ jobs: # Setup .npmrc file to publish to npm - uses: actions/setup-node@v4 with: - node-version-file: '.nvmrc' + node-version-file: '.node-version' registry-url: 'https://registry.npmjs.org' scope: '@jamesives' @@ -60,7 +60,7 @@ jobs: # Setup .npmrc file to publish to GitHub Packages - uses: actions/setup-node@v4 with: - node-version-file: '.nvmrc' + node-version-file: '.node-version' registry-url: 'https://npm.pkg.github.com' scope: '@jamesives' diff --git a/.node-version b/.node-version new file mode 100644 index 00000000..bb8c76c6 --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +v22.11.0 diff --git a/.nvmrc b/.nvmrc deleted file mode 100644 index 790e1105..00000000 --- a/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -v20.10.0 diff --git a/__tests__/fetch.test.ts b/__tests__/fetch.test.ts index 9140af5f..56ed1d4e 100644 --- a/__tests__/fetch.test.ts +++ b/__tests__/fetch.test.ts @@ -1,17 +1,18 @@ import {retrieveData, generateExport} from '../src/fetch' -import nock from 'nock' jest.setTimeout(1000000) -nock.enableNetConnect() describe('fetch', () => { describe('retrieveData', () => { - afterEach(nock.cleanAll) - afterAll(nock.restore) + afterEach(() => { + jest.clearAllMocks() + }) it('should return some data', async () => { - nock('https://jamesiv.es').get('/').reply(200, { - data: '12345' + global.fetch = jest.fn().mockResolvedValue({ + ok: true, + json: jest.fn().mockResolvedValue({data: '12345'}), + text: jest.fn().mockResolvedValue('{"data":"12345"}') }) const data = await retrieveData({ @@ -22,11 +23,11 @@ describe('fetch', () => { }) it('should handle the triple bracket replacements', async () => { - nock('https://jives.dev/') - .post('/', '{"bestCat":"montezuma"}') - .reply(200, { - data: '12345' - }) + global.fetch = jest.fn().mockResolvedValue({ + ok: true, + json: jest.fn().mockResolvedValue({data: '12345'}), + text: jest.fn().mockResolvedValue('{"data":"12345"}') + }) const data = await retrieveData({ debug: true, @@ -45,8 +46,6 @@ describe('fetch', () => { it('should error if improperly formatted json is passed in', async () => { try { - nock('https://jamesiv.es').get('/').reply(200) - await retrieveData({ debug: true, endpoint: 'https://example.com', @@ -61,8 +60,10 @@ describe('fetch', () => { }) it('should error if the response is not ok', async () => { - nock('https://jamesiv.es').post('/').reply(404, { - a: 1 + global.fetch = jest.fn().mockResolvedValue({ + ok: false, + json: jest.fn().mockResolvedValue({a: 1}), + text: jest.fn().mockResolvedValue('{"a":1}') }) try { @@ -83,18 +84,18 @@ describe('fetch', () => { } }) - it('should error if the response is not ok after several retrys', async () => { + it('should error if the response is not ok after several retries', async () => { jest.setTimeout(1000000) - - try { - nock('https://jives.dev').get('/').once().replyWithError({ - message: 'This is catastrophic' - }) - - nock('https://jives.dev').get('/').reply(200, { - data: '12345' + global.fetch = jest + .fn() + .mockRejectedValueOnce(new Error('This is catastrophic')) + .mockResolvedValueOnce({ + ok: true, + json: jest.fn().mockResolvedValue({data: '12345'}), + text: jest.fn().mockResolvedValue('{"data":"12345"}') }) + try { await retrieveData({ debug: true, endpoint: 'https://jives.dev', @@ -117,7 +118,7 @@ describe('fetch', () => { expect(process.env['fetchApiData']).toBe('{"bestCat":"montezuma"}') }) - it('should save non standard file types', async () => { + it('should save non-standard file types', async () => { await generateExport({ data: 'hello', format: 'txt', diff --git a/__tests__/lib.test.ts b/__tests__/lib.test.ts index 70dd6777..0b3af757 100644 --- a/__tests__/lib.test.ts +++ b/__tests__/lib.test.ts @@ -1,5 +1,4 @@ import {exportVariable, setFailed} from '@actions/core' -import nock from 'nock' import {action} from '../src/constants' import run from '../src/lib' import '../src/main' @@ -15,38 +14,49 @@ jest.mock('@actions/core', () => ({ describe('lib', () => { beforeEach(() => { - nock('https://jamesiv.es').get('/').reply(200, { - data: '12345' + jest.clearAllMocks() + + global.fetch = jest.fn().mockResolvedValue({ + json: jest.fn().mockResolvedValue({data: '12345'}), + text: jest.fn().mockResolvedValue('{"data":"12345"}'), + ok: true }) }) afterEach(() => { - nock.restore() Object.assign(action, JSON.parse(originalAction)) }) - afterEach(nock.cleanAll) - it('should run through the commands', async () => { Object.assign(action, { debug: true, - endpoint: 'https://jamesiv.es', + endpoint: 'https://jives.dev', setOutput: true }) + await run(action) - expect(exportVariable).toHaveBeenCalled() + expect(exportVariable).toHaveBeenCalledTimes(1) + expect(global.fetch).toHaveBeenCalledWith( + 'https://jives.dev', + expect.any(Object) + ) }) it('should run through the commands but not save output', async () => { Object.assign(action, { debug: true, - endpoint: 'https://jamesiv.es', + endpoint: 'https://jives.dev', setOutput: false }) + await run(action) expect(exportVariable).toHaveBeenCalledTimes(0) + expect(global.fetch).toHaveBeenCalledWith( + 'https://jives.dev', + expect.any(Object) + ) }) it('should throw an error if no endpoint is provided', async () => { @@ -58,6 +68,7 @@ describe('lib', () => { try { await run(action) } catch (error) { + console.error(error) expect(setFailed).toHaveBeenCalled() } }) @@ -73,6 +84,7 @@ describe('lib', () => { try { await run(action) } catch (error) { + console.error(error) expect(setFailed).toHaveBeenCalled() } }) diff --git a/eslint.config.mjs b/eslint.config.mjs index 94a01764..33301eb0 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -17,7 +17,7 @@ export default tseslint.config( }, rules: { 'jest/no-conditional-expect': 'off', - '@typescript-eslint/ban-types': [ + '@typescript-eslint/no-restricted-types': [ 'error', { types: { diff --git a/package.json b/package.json index 63cef2bb..267c8820 100644 --- a/package.json +++ b/package.json @@ -38,7 +38,6 @@ "@actions/core": "1.11.1", "@actions/io": "1.1.3", "async-retry": "1.3.3", - "cross-fetch": "4.0.0", "mustache": "4.2.0" }, "devDependencies": { @@ -55,7 +54,6 @@ "eslint-plugin-prettier": "5.2.1", "jest": "29.7.0", "jest-circus": "29.7.0", - "nock": "13.5.5", "prettier": "3.3.3", "ts-jest": "29.2.5", "typescript": "5.6.3", diff --git a/src/constants.ts b/src/constants.ts index 95c53c48..22f0ac02 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -1,6 +1,9 @@ import {getInput} from '@actions/core' import {isNullOrUndefined} from './util' +/** + * Required action data that gets initialized when running within the GitHub Actions environment. + */ export interface ActionInterface { /** Allows you to log the retrieved data to the terminal. */ debug?: boolean @@ -28,6 +31,9 @@ export interface ActionInterface { variableName?: string } +/** + * Required data to fetch the data. + */ export interface DataInterface { /** Allows you to log the retrieved data to the terminal. */ debug?: boolean @@ -43,6 +49,9 @@ export interface DataInterface { retry?: boolean | null } +/** + * Required data to export the data. + */ export interface ExportInterface { /** The data to save. */ data: string @@ -60,7 +69,9 @@ export interface ExportInterface { variableName?: string } -// Required action data that gets initialized when running within the GitHub Actions environment. +/** + * Required action data that gets initialized when running within the GitHub Actions environment. + */ export const action = { debug: !isNullOrUndefined(getInput('debug')) ? getInput('debug').toLowerCase() === 'true' diff --git a/src/fetch.ts b/src/fetch.ts index bb3200ff..726f1a0d 100644 --- a/src/fetch.ts +++ b/src/fetch.ts @@ -5,14 +5,15 @@ import { debug } from '@actions/core' import {mkdirP} from '@actions/io' -import 'cross-fetch/polyfill' import {promises as fs} from 'fs' import {render} from 'mustache' import retryRequest from 'async-retry' import {DataInterface, ExportInterface, Status} from './constants' import {parseData} from './util' -/* Fetches or Posts data to an API. If auth is provided it will replace the mustache variables with the data from it. */ +/** + * Retrieves data from an API endpoint. + */ export async function retrieveData({ debug: requestDebug, endpoint, @@ -67,7 +68,9 @@ export async function retrieveData({ } } -/* Saves the data to the local file system and exports an environment variable containing the retrieved data. */ +/** + * Generates an export file from the data provided. + */ export async function generateExport({ data, encoding, diff --git a/src/lib.ts b/src/lib.ts index faf9c335..06746c3b 100644 --- a/src/lib.ts +++ b/src/lib.ts @@ -31,6 +31,7 @@ export default async function run( hasRequiredParameters(settings) let auth = '' + if (settings.tokenEndpoint) { auth = await retrieveData({ debug: settings.debug, diff --git a/src/util.ts b/src/util.ts index 158974c7..d30da133 100644 --- a/src/util.ts +++ b/src/util.ts @@ -1,10 +1,14 @@ import {ActionInterface} from './constants' -/* Utility function that checks to see if a value is undefined or not. */ +/** + * Checks to see if a value is null or undefined. + */ export const isNullOrUndefined = (value: string | undefined | null): boolean => typeof value === 'undefined' || value === null || value === '' -/* Checks for the required inputs. Throws an error if any case is matched. */ +/** + * Checks to see if the action has the required parameters to run. + */ export const hasRequiredParameters = (action: ActionInterface): void => { if (isNullOrUndefined(action.endpoint)) { throw new Error( @@ -13,6 +17,9 @@ export const hasRequiredParameters = (action: ActionInterface): void => { } } +/** + * Extracts the error message from an error object or string. + */ export const extractErrorMessage = (error: unknown): string => error instanceof Error ? error.message @@ -20,7 +27,9 @@ export const extractErrorMessage = (error: unknown): string => ? error : JSON.stringify(error) -/* Attempt to parse data as JSON and catch any errors. */ +/** + * Parses a string into a JSON object. + */ export const parseData = (data: string): Record | null => { try { return JSON.parse(data) diff --git a/yarn.lock b/yarn.lock index 55d3198d..6ee59056 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1518,13 +1518,6 @@ create-jest@^29.7.0: jest-util "^29.7.0" prompts "^2.0.1" -cross-fetch@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-4.0.0.tgz#f037aef1580bb3a1a35164ea2a848ba81b445983" - integrity sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g== - dependencies: - node-fetch "^2.6.12" - cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -2494,10 +2487,6 @@ json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" -json-stringify-safe@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - json5@^2.1.2, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" @@ -2637,22 +2626,6 @@ natural-compare@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" -nock@13.5.5: - version "13.5.5" - resolved "https://registry.yarnpkg.com/nock/-/nock-13.5.5.tgz#cd1caaca281d42be17d51946367a3d53a6af3e78" - integrity sha512-XKYnqUrCwXC8DGG1xX4YH5yNIrlh9c065uaMZZHUoeUUINTOyt+x/G+ezYk0Ft6ExSREVIs+qBJDK503viTfFA== - dependencies: - debug "^4.1.0" - json-stringify-safe "^5.0.1" - propagate "^2.0.0" - -node-fetch@^2.6.12: - version "2.7.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d" - integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A== - dependencies: - whatwg-url "^5.0.0" - node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -2832,10 +2805,6 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.4" -propagate@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" - punycode@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -3061,11 +3030,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -tr46@~0.0.3: - version "0.0.3" - resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" - integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= - ts-api-utils@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" @@ -3159,19 +3123,6 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" -webidl-conversions@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" - integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= - -whatwg-url@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" - integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= - dependencies: - tr46 "~0.0.3" - webidl-conversions "^3.0.0" - which@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"