From d5d74c5ac4200c1e0ceaf994f2ff71086894b2c3 Mon Sep 17 00:00:00 2001 From: Kanad Gupta Date: Tue, 10 Dec 2024 19:18:50 -0600 Subject: [PATCH] fix: bring back #1117 without breaking everything (#1120) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 🧰 Changes we hit a bit of a wild edge case where the github action was only breaking in production builds due to how oclif loads the `package.json` and the only way we caught it was with [this failure](https://github.com/readmeio/rdme/actions/runs/12267183540/job/34226921877). this PR reverts https://github.com/readmeio/rdme/pull/1119 (which in turn brings back https://github.com/readmeio/rdme/pull/1117) with a slight tweak in https://github.com/readmeio/rdme/pull/1120/commits/f9461b430e2318c00731c4f75d1506cd593d4970 to do the following: - make our import paths friendlier to github actions - manually copy over the `package.json` to our `dist/` directory whenever we run `npm run build`. TS was automatically handling this when we were using JSON imports before but now it's not able to pick up on the import so we have to copy it over ourselves. additionally in https://github.com/readmeio/rdme/pull/1120/commits/669cb4f2854ff775023eeec3895b70998c70f920, i added a little check so we can catch these sorts of things better going forward. ## 🧬 QA & Testing Provide as much information as you can on how to test what you've done. --- .github/workflows/ci.yml | 8 ++++++ .github/workflows/release.yml | 9 +++++++ __tests__/commands/logout.test.ts | 2 +- __tests__/commands/open.test.ts | 2 +- __tests__/commands/whoami.test.ts | 2 +- __tests__/helpers/get-gha-setup.ts | 2 +- __tests__/lib/createGHA.test.ts | 2 +- __tests__/lib/getPkgVersion.test.ts | 8 +++--- bin/dev.js | 2 +- bin/run.js | 4 +-- bin/set-version-output.js | 2 +- package.json | 2 +- src/lib/configstore.ts | 2 +- src/lib/createGHA/index.ts | 2 +- src/lib/{getPkgVersion.ts => getPkg.ts} | 35 ++++++++++++++++++++----- src/lib/readmeAPIFetch.ts | 5 ++-- 16 files changed, 62 insertions(+), 27 deletions(-) rename src/lib/{getPkgVersion.ts => getPkg.ts} (56%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 48ac6f03c..f3135c2f7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -113,3 +113,11 @@ jobs: uses: ./rdme-repo/ with: rdme: openapi "oas-examples-repo/3.1/json/petstore.json" --key "${{ secrets.RDME_TEST_PROJECT_API_KEY }}" --id=${{ secrets.RDME_TEST_PROJECT_API_SETTING }} + + # this is a test to ensure that the rdme github action can run properly + # the way that our users invoke it + - name: E2E run of `openapi validate` on `next` branch + uses: readmeio/rdme@next + if: ${{ github.ref }} == 'refs/heads/next' + with: + rdme: openapi validate oas-examples-repo/3.1/json/petstore.json diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 818bef5a9..593358d0a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -48,3 +48,12 @@ jobs: with: github_token: ${{ secrets.RELEASE_GH_TOKEN }} branch: next + + # quick assertion to validate that rdme CLI can be installed and run on ubuntu + - name: Install `rdme` from npm + if: ${{ github.ref }} == 'refs/heads/next' + run: npm install -g rdme@next + - name: Print rdme CLI version + if: ${{ github.ref }} == 'refs/heads/next' + run: rdme --version + timeout-minutes: 1 diff --git a/__tests__/commands/logout.test.ts b/__tests__/commands/logout.test.ts index b0fab24e6..901e7dea9 100644 --- a/__tests__/commands/logout.test.ts +++ b/__tests__/commands/logout.test.ts @@ -1,6 +1,6 @@ import { describe, afterEach, beforeAll, it, expect } from 'vitest'; -import pkg from '../../package.json'; +import pkg from '../../package.json' with { type: 'json' }; import Command from '../../src/commands/logout.js'; import configStore from '../../src/lib/configstore.js'; import { runCommandAndReturnResult } from '../helpers/oclif.js'; diff --git a/__tests__/commands/open.test.ts b/__tests__/commands/open.test.ts index 80b961dd3..3ab9829f0 100644 --- a/__tests__/commands/open.test.ts +++ b/__tests__/commands/open.test.ts @@ -3,7 +3,7 @@ import type { Version } from '../../src/commands/versions/index.js'; import chalk from 'chalk'; import { describe, afterEach, beforeAll, it, expect } from 'vitest'; -import pkg from '../../package.json'; +import pkg from '../../package.json' with { type: 'json' }; import Command from '../../src/commands/open.js'; import configStore from '../../src/lib/configstore.js'; import { getAPIv1Mock } from '../helpers/get-api-mock.js'; diff --git a/__tests__/commands/whoami.test.ts b/__tests__/commands/whoami.test.ts index 10c898255..aecd0bbee 100644 --- a/__tests__/commands/whoami.test.ts +++ b/__tests__/commands/whoami.test.ts @@ -1,6 +1,6 @@ import { describe, afterEach, it, expect, beforeAll } from 'vitest'; -import pkg from '../../package.json'; +import pkg from '../../package.json' with { type: 'json' }; import Command from '../../src/commands/whoami.js'; import configStore from '../../src/lib/configstore.js'; import { runCommandAndReturnResult } from '../helpers/oclif.js'; diff --git a/__tests__/helpers/get-gha-setup.ts b/__tests__/helpers/get-gha-setup.ts index 528f6ca80..cd382c773 100644 --- a/__tests__/helpers/get-gha-setup.ts +++ b/__tests__/helpers/get-gha-setup.ts @@ -6,7 +6,7 @@ import { vi } from 'vitest'; import configstore from '../../src/lib/configstore.js'; import { git } from '../../src/lib/createGHA/index.js'; -import * as getPkgVersion from '../../src/lib/getPkgVersion.js'; +import * as getPkgVersion from '../../src/lib/getPkg.js'; import getGitRemoteMock from './get-git-mock.js'; diff --git a/__tests__/lib/createGHA.test.ts b/__tests__/lib/createGHA.test.ts index a1cd3d9b8..943bb90f9 100644 --- a/__tests__/lib/createGHA.test.ts +++ b/__tests__/lib/createGHA.test.ts @@ -10,7 +10,7 @@ import { describe, beforeEach, afterEach, it, expect, vi, type MockInstance, bef import configstore from '../../src/lib/configstore.js'; import { getConfigStoreKey, getGHAFileName, git } from '../../src/lib/createGHA/index.js'; -import { getMajorPkgVersion } from '../../src/lib/getPkgVersion.js'; +import { getMajorPkgVersion } from '../../src/lib/getPkg.js'; import { after, before } from '../helpers/get-gha-setup.js'; import getGitRemoteMock from '../helpers/get-git-mock.js'; import ghaWorkflowSchema from '../helpers/github-workflow-schema.json' with { type: 'json' }; diff --git a/__tests__/lib/getPkgVersion.test.ts b/__tests__/lib/getPkgVersion.test.ts index 9bf6e7285..ac3f6aff9 100644 --- a/__tests__/lib/getPkgVersion.test.ts +++ b/__tests__/lib/getPkgVersion.test.ts @@ -3,7 +3,7 @@ import semver from 'semver'; import { describe, beforeEach, afterEach, it, expect, vi, type MockInstance } from 'vitest'; import pkg from '../../package.json' with { type: 'json' }; -import { getNodeVersion, getPkgVersion } from '../../src/lib/getPkgVersion.js'; +import { getNodeVersion, getPkgVersion, getPkgVersionFromNPM } from '../../src/lib/getPkg.js'; describe('#getNodeVersion()', () => { it('should extract version that matches range in package.json', () => { @@ -27,7 +27,7 @@ describe('#getPkgVersion()', () => { }); it('should grab version from package.json by default', () => { - return expect(getPkgVersion()).resolves.toBe(pkg.version); + return expect(getPkgVersion()).toBe(pkg.version); }); it('should fetch version from npm registry', async () => { @@ -35,7 +35,7 @@ describe('#getPkgVersion()', () => { .get('/rdme') .reply(200, { 'dist-tags': { latest: '1.0' } }); - await expect(getPkgVersion('latest')).resolves.toBe('1.0'); + await expect(getPkgVersionFromNPM('latest')).resolves.toBe('1.0'); mock.done(); }); @@ -43,7 +43,7 @@ describe('#getPkgVersion()', () => { it('should fallback if npm registry fails', async () => { const mock = nock('https://registry.npmjs.com', { encodedQueryParams: true }).get('/rdme').reply(500); - await expect(getPkgVersion('latest')).resolves.toBe(pkg.version); + await expect(getPkgVersionFromNPM('latest')).resolves.toBe(pkg.version); mock.done(); }); diff --git a/bin/dev.js b/bin/dev.js index 7122c2827..c87b65b4a 100755 --- a/bin/dev.js +++ b/bin/dev.js @@ -1,4 +1,4 @@ -#!/usr/bin/env -S npx tsx +#!/usr/bin/env npx tsx async function main() { const { execute } = await import('@oclif/core'); diff --git a/bin/run.js b/bin/run.js index 4a32f3b6b..0875bc524 100755 --- a/bin/run.js +++ b/bin/run.js @@ -1,6 +1,4 @@ -#!/usr/bin/env -S node --no-warnings=ExperimentalWarning -// ^ we need this env variable above to hide the ExperimentalWarnings -// source: https://github.com/nodejs/node/issues/10802#issuecomment-573376999 +#!/usr/bin/env node import stringArgv from 'string-argv'; diff --git a/bin/set-version-output.js b/bin/set-version-output.js index 41de6484b..0aee75ce5 100755 --- a/bin/set-version-output.js +++ b/bin/set-version-output.js @@ -3,7 +3,7 @@ import * as core from '@actions/core'; // eslint-disable-next-line import/extensions -import { getNodeVersion, getMajorPkgVersion } from '../dist/lib/getPkgVersion.js'; +import { getNodeVersion, getMajorPkgVersion } from '../dist/lib/getPkg.js'; /** * Sets output parameters for GitHub Actions workflow so we can do diff --git a/package.json b/package.json index 7ea72f29f..85bd422c3 100644 --- a/package.json +++ b/package.json @@ -111,7 +111,7 @@ "vitest": "^2.0.5" }, "scripts": { - "build": "tsc", + "build": "tsc && ln package.json dist/package.json", "build:docs": "oclif readme --multi --output-dir documentation/commands --no-aliases", "build:gha": "npm run build && rollup --config", "build:gha:prod": "npm run build:gha -- --environment PRODUCTION_BUILD", diff --git a/src/lib/configstore.ts b/src/lib/configstore.ts index 7fc7fccc0..d4517a480 100644 --- a/src/lib/configstore.ts +++ b/src/lib/configstore.ts @@ -1,6 +1,6 @@ import Configstore from 'configstore'; -import pkg from '../package.json' with { type: 'json' }; +import { pkg } from './getPkg.js'; const configstore = new Configstore( /** diff --git a/src/lib/createGHA/index.ts b/src/lib/createGHA/index.ts index 539c428ff..ffa744099 100644 --- a/src/lib/createGHA/index.ts +++ b/src/lib/createGHA/index.ts @@ -8,7 +8,7 @@ import prompts from 'prompts'; import { simpleGit } from 'simple-git'; import configstore from '../configstore.js'; -import { getMajorPkgVersion } from '../getPkgVersion.js'; +import { getMajorPkgVersion } from '../getPkg.js'; import isCI, { isNpmScript, isTest } from '../isCI.js'; import { info } from '../logger.js'; import promptTerminal from '../promptWrapper.js'; diff --git a/src/lib/getPkgVersion.ts b/src/lib/getPkg.ts similarity index 56% rename from src/lib/getPkgVersion.ts rename to src/lib/getPkg.ts index 335f7929b..578cbdb47 100644 --- a/src/lib/getPkgVersion.ts +++ b/src/lib/getPkg.ts @@ -1,8 +1,8 @@ import type { Hook } from '@oclif/core'; -import semver from 'semver'; +import { readFileSync } from 'node:fs'; -import pkg from '../package.json' with { type: 'json' }; +import semver from 'semver'; import { error } from './logger.js'; @@ -13,6 +13,15 @@ const registryUrl = 'https://registry.npmjs.com/rdme'; */ type npmDistTag = 'latest'; +/** + * A synchronous function that reads the `package.json` file for use elsewhere. + * Until we drop support Node.js 20, we need to import this way to avoid ExperimentalWarning outputs. + * + * @see {@link https://nodejs.org/docs/latest-v20.x/api/esm.html#import-attributes} + * @see {@link https://www.stefanjudis.com/snippets/how-to-import-json-files-in-es-modules-node-js/} + */ +export const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), { encoding: 'utf-8' })); + /** * Return the major Node.js version specified in our `package.json` config. * @@ -27,6 +36,18 @@ export function getNodeVersion(): string { return parsedVersion.version; } +/** + * The current `rdme` version, as specified in the `package.json` + * or in the oclif hook context. + * + * @example "8.0.0" + * @note we mock this function in our snapshots + * @see {@link https://stackoverflow.com/a/54245672} + */ +export function getPkgVersion(this: Hook.Context | void): string { + return this?.config?.version || pkg.version; +} + /** * The current `rdme` version * @@ -34,20 +55,20 @@ export function getNodeVersion(): string { * the version from the `package.json` is returned. * @example "8.0.0" * @see {@link https://docs.npmjs.com/adding-dist-tags-to-packages} - * @note we mock this function in our snapshots, hence it's not the default + * @note we mock this function in our snapshots * @see {@link https://stackoverflow.com/a/54245672} */ -export async function getPkgVersion(this: Hook.Context | void, npmDistTag?: npmDistTag): Promise { +export async function getPkgVersionFromNPM(this: Hook.Context | void, npmDistTag?: npmDistTag): Promise { if (npmDistTag) { return fetch(registryUrl) .then(res => res.json() as Promise<{ 'dist-tags': Record }>) .then(body => body['dist-tags'][npmDistTag]) .catch(err => { error(`error fetching version from npm registry: ${err.message}`); - return pkg.version; + return getPkgVersion.call(this); }); } - return this?.config?.version || pkg.version; + return getPkgVersion.call(this); } /** @@ -56,5 +77,5 @@ export async function getPkgVersion(this: Hook.Context | void, npmDistTag?: npmD * @example 8 */ export async function getMajorPkgVersion(this: Hook.Context | void, npmDistTag?: npmDistTag): Promise { - return semver.major(await getPkgVersion.call(this, npmDistTag)); + return semver.major(await getPkgVersionFromNPM.call(this, npmDistTag)); } diff --git a/src/lib/readmeAPIFetch.ts b/src/lib/readmeAPIFetch.ts index 920ca2b79..56aab4b4e 100644 --- a/src/lib/readmeAPIFetch.ts +++ b/src/lib/readmeAPIFetch.ts @@ -5,11 +5,10 @@ import path from 'node:path'; import mime from 'mime-types'; import { ProxyAgent } from 'undici'; -import pkg from '../package.json' with { type: 'json' }; - import { APIv1Error } from './apiError.js'; import config from './config.js'; import { git } from './createGHA/index.js'; +import { getPkgVersion } from './getPkg.js'; import isCI, { ciName, isGHA } from './isCI.js'; import { debug, warn } from './logger.js'; @@ -90,7 +89,7 @@ function parseWarningHeader(header: string): WarningHeader[] { */ export function getUserAgent() { const gh = isGHA() ? '-github' : ''; - return `rdme${gh}/${pkg.version}`; + return `rdme${gh}/${getPkgVersion()}`; } /**