From 4c3ab552b63017c896429cca9398592d703eeafc Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Wed, 28 Jun 2023 09:25:29 +0200 Subject: [PATCH] fix: allow specifying ci file in check-project (#1317) Not all projects use js-test-and-release.yml as their main CI file so allow specifying something different. --- src/check-project/check-monorepo-readme.js | 5 +- src/check-project/check-readme.js | 5 +- src/check-project/index.js | 46 +++++++++++++----- src/check-project/manifests/untyped-esm.js | 56 ++++++++++++++++++++++ src/check-project/readme/header.js | 23 ++++----- 5 files changed, 108 insertions(+), 27 deletions(-) create mode 100644 src/check-project/manifests/untyped-esm.js diff --git a/src/check-project/check-monorepo-readme.js b/src/check-project/check-monorepo-readme.js index df8eaa392..e501c5093 100644 --- a/src/check-project/check-monorepo-readme.js +++ b/src/check-project/check-monorepo-readme.js @@ -17,8 +17,9 @@ import { * @param {string} repoUrl * @param {string} defaultBranch * @param {string[]} projectDirs + * @param {string} ciFile */ -export async function checkMonorepoReadme (projectDir, repoUrl, defaultBranch, projectDirs) { +export async function checkMonorepoReadme (projectDir, repoUrl, defaultBranch, projectDirs, ciFile) { const repoParts = repoUrl.split('/') const repoName = repoParts.pop() const repoOwner = repoParts.pop() @@ -47,7 +48,7 @@ export async function checkMonorepoReadme (projectDir, repoUrl, defaultBranch, p const file = parseMarkdown(readmeContents) // create basic readme with heading, CI link, etc - const readme = parseMarkdown(HEADER(pkg, repoOwner, repoName, defaultBranch)) + const readme = parseMarkdown(HEADER(pkg, repoOwner, repoName, defaultBranch, ciFile)) // remove existing header, CI link, etc /** @type {import('mdast').Root} */ diff --git a/src/check-project/check-readme.js b/src/check-project/check-readme.js index 53c7b2917..0fb946b0d 100644 --- a/src/check-project/check-readme.js +++ b/src/check-project/check-readme.js @@ -16,9 +16,10 @@ import { * @param {string} projectDir * @param {string} repoUrl * @param {string} defaultBranch + * @param {string} ciFile * @param {any} [rootManifest] */ -export async function checkReadme (projectDir, repoUrl, defaultBranch, rootManifest) { +export async function checkReadme (projectDir, repoUrl, defaultBranch, ciFile, rootManifest) { const repoParts = repoUrl.split('/') const repoName = repoParts.pop() const repoOwner = repoParts.pop() @@ -47,7 +48,7 @@ export async function checkReadme (projectDir, repoUrl, defaultBranch, rootManif const file = parseMarkdown(readmeContents) // create basic readme with heading, CI link, etc - const readme = parseMarkdown(HEADER(pkg, repoOwner, repoName, defaultBranch)) + const readme = parseMarkdown(HEADER(pkg, repoOwner, repoName, defaultBranch, ciFile)) // remove existing header, CI link, etc /** @type {import('mdast').Root} */ diff --git a/src/check-project/index.js b/src/check-project/index.js index 5db27cc5b..9dfb42240 100755 --- a/src/check-project/index.js +++ b/src/check-project/index.js @@ -22,6 +22,7 @@ import { typedCJSManifest } from './manifests/typed-cjs.js' import { typedESMManifest } from './manifests/typed-esm.js' import { typescriptManifest } from './manifests/typescript.js' import { untypedCJSManifest } from './manifests/untyped-cjs.js' +import { untypedESMManifest } from './manifests/untyped-esm.js' import { sortManifest, ensureFileHasContents, @@ -98,8 +99,9 @@ async function getConfig (projectDir) { * @param {any} manifest * @param {string} branchName * @param {string} repoUrl + * @param {string} ciFile */ -async function processMonorepo (projectDir, manifest, branchName, repoUrl) { +async function processMonorepo (projectDir, manifest, branchName, repoUrl, ciFile) { const workspaces = manifest.workspaces if (!workspaces || !Array.isArray(workspaces)) { @@ -130,7 +132,7 @@ async function processMonorepo (projectDir, manifest, branchName, repoUrl) { console.info('Found monorepo project', pkg.name) - await processModule(subProjectDir, pkg, branchName, repoUrl, homePage, manifest) + await processModule(subProjectDir, pkg, branchName, repoUrl, homePage, ciFile, manifest) projectDirs.push(subProjectDir) } @@ -148,7 +150,7 @@ async function processMonorepo (projectDir, manifest, branchName, repoUrl) { })) await checkLicenseFiles(projectDir) await checkBuildFiles(projectDir, branchName, repoUrl) - await checkMonorepoReadme(projectDir, repoUrl, branchName, projectDirs) + await checkMonorepoReadme(projectDir, repoUrl, branchName, projectDirs, ciFile) await checkMonorepoFiles(projectDir) } @@ -306,9 +308,10 @@ function addReferences (deps, references, refs) { * @param {any} manifest * @param {string} branchName * @param {string} repoUrl + * @param {string} ciFile */ -async function processProject (projectDir, manifest, branchName, repoUrl) { - await processModule(projectDir, manifest, branchName, repoUrl) +async function processProject (projectDir, manifest, branchName, repoUrl, ciFile) { + await processModule(projectDir, manifest, branchName, repoUrl, repoUrl, ciFile) await checkBuildFiles(projectDir, branchName, repoUrl) } @@ -326,9 +329,10 @@ function isAegirProject (manifest) { * @param {string} branchName * @param {string} repoUrl * @param {string} homePage + * @param {string} ciFile * @param {any} [rootManifest] */ -async function processModule (projectDir, manifest, branchName, repoUrl, homePage = repoUrl, rootManifest) { +async function processModule (projectDir, manifest, branchName, repoUrl, homePage = repoUrl, ciFile, rootManifest) { if (!isAegirProject(manifest) && manifest.name !== 'aegir') { throw new Error(`"${projectDir}" is not an aegir project`) } @@ -351,7 +355,10 @@ async function processModule (projectDir, manifest, branchName, repoUrl, homePag // 3. CJS, no types let typedCJS = cjs && hasMain && types - // 3. CJS, no types + // 4. ESM, no types + let untypedESM = esm && hasMain + + // 5. CJS, no types let untypedCJS = cjs && hasMain let proposedManifest = {} @@ -361,10 +368,10 @@ async function processModule (projectDir, manifest, branchName, repoUrl, homePag const { projectType } = await prompt.get({ properties: { projectType: { - description: 'Project type: typescript | typedESM | typedCJS | untypedCJS', + description: 'Project type: typescript | typedESM | typedCJS | untypedESM | untypedCJS', required: true, conform: (value) => { - return ['typescript', 'typedESM', 'typedCJS', 'untypedCJS'].includes(value) + return ['typescript', 'typedESM', 'typedCJS', 'untypedESM', 'untypedCJS'].includes(value) }, default: 'typescript' } @@ -377,6 +384,8 @@ async function processModule (projectDir, manifest, branchName, repoUrl, homePag typedESM = true } else if (projectType === 'typedCJS') { typedCJS = true + } else if (projectType === 'untypedESM') { + untypedESM = true } else if (projectType === 'untypedCJS') { untypedCJS = true } else { @@ -393,6 +402,9 @@ async function processModule (projectDir, manifest, branchName, repoUrl, homePag } else if (typedCJS) { console.info('Typed CJS project detected') proposedManifest = await typedCJSManifest(manifest, branchName, repoUrl, homePage) + } else if (untypedESM) { + console.info('Untyped ESM project detected') + proposedManifest = await untypedESMManifest(manifest, branchName, repoUrl, homePage) } else if (untypedCJS) { console.info('Untyped CJS project detected') proposedManifest = await untypedCJSManifest(manifest, branchName, repoUrl, homePage) @@ -411,7 +423,7 @@ async function processModule (projectDir, manifest, branchName, repoUrl, homePag } await checkLicenseFiles(projectDir) - await checkReadme(projectDir, repoUrl, branchName, rootManifest) + await checkReadme(projectDir, repoUrl, branchName, ciFile, rootManifest) } export default new Listr([ @@ -424,11 +436,21 @@ export default new Listr([ const manifest = fs.readJSONSync(path.join(projectDir, 'package.json')) const monorepo = manifest.workspaces != null + const ciFile = (await prompt.get({ + properties: { + ciFile: { + description: 'ciFile', + required: true, + default: 'js-test-and-release.yml' + } + } + })).ciFile.toString() + if (monorepo) { console.info('monorepo project detected') - await processMonorepo(projectDir, manifest, branchName, repoUrl) + await processMonorepo(projectDir, manifest, branchName, repoUrl, ciFile) } else { - await processProject(projectDir, manifest, branchName, repoUrl) + await processProject(projectDir, manifest, branchName, repoUrl, ciFile) } } } diff --git a/src/check-project/manifests/untyped-esm.js b/src/check-project/manifests/untyped-esm.js new file mode 100644 index 000000000..e1547c726 --- /dev/null +++ b/src/check-project/manifests/untyped-esm.js @@ -0,0 +1,56 @@ +import mergeOptions from 'merge-options' +import { semanticReleaseConfig } from '../semantic-release-config.js' +import { + sortFields, + constructManifest +} from '../utils.js' + +const merge = mergeOptions.bind({ ignoreUndefined: true }) + +/** + * @param {any} manifest + * @param {string} branchName + * @param {string} repoUrl + * @param {string} [homePage] + */ +export async function untypedESMManifest (manifest, branchName, repoUrl, homePage = repoUrl) { + let proposedManifest = constructManifest(manifest, { + type: 'module', + files: [ + 'src', + 'dist', + '!dist/test', + '!**/*.tsbuildinfo' + ], + exports: { + '.': { + types: './dist/src/index.d.ts', + import: './src/index.js' + } + }, + eslintConfig: merge({ + extends: 'ipfs', + parserOptions: { + sourceType: 'module' + } + }, manifest.eslintConfig), + release: (manifest.scripts?.release?.includes('semantic-release') || manifest.scripts?.release?.includes('aegir release')) ? semanticReleaseConfig(branchName) : undefined + }, repoUrl, homePage) + + const rest = { + ...sortFields(manifest) + } + + for (const key of Object.keys(proposedManifest)) { + delete rest[key] + } + + proposedManifest = { + ...proposedManifest, + ...rest, + contributors: undefined, + leadMaintainer: undefined + } + + return proposedManifest +} diff --git a/src/check-project/readme/header.js b/src/check-project/readme/header.js index 36acb106d..3159763c0 100644 --- a/src/check-project/readme/header.js +++ b/src/check-project/readme/header.js @@ -1,27 +1,27 @@ /** - * @type {Record string>} + * @type {Record string>} */ const BADGES = { - libp2p: (repoOwner, repoName, defaultBranch) => ` + libp2p: (repoOwner, repoName, defaultBranch, ciFile) => ` [![libp2p.io](https://img.shields.io/badge/project-libp2p-yellow.svg?style=flat-square)](http://libp2p.io/) [![Discuss](https://img.shields.io/discourse/https/discuss.libp2p.io/posts.svg?style=flat-square)](https://discuss.libp2p.io) [![codecov](https://img.shields.io/codecov/c/github/${repoOwner}/${repoName}.svg?style=flat-square)](https://codecov.io/gh/${repoOwner}/${repoName}) -[![CI](https://img.shields.io/github/actions/workflow/status/${repoOwner}/${repoName}/js-test-and-release.yml?branch=${defaultBranch}&style=flat-square)](https://github.com/${repoOwner}/${repoName}/actions/workflows/js-test-and-release.yml?query=branch%3A${defaultBranch}) +[![CI](https://img.shields.io/github/actions/workflow/status/${repoOwner}/${repoName}/${ciFile}?branch=${defaultBranch}&style=flat-square)](https://github.com/${repoOwner}/${repoName}/actions/workflows/${ciFile}?query=branch%3A${defaultBranch}) `, - ipfs: (repoOwner, repoName, defaultBranch) => ` + ipfs: (repoOwner, repoName, defaultBranch, ciFile) => ` [![ipfs.tech](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](https://ipfs.tech) [![Discuss](https://img.shields.io/discourse/https/discuss.ipfs.tech/posts.svg?style=flat-square)](https://discuss.ipfs.tech) [![codecov](https://img.shields.io/codecov/c/github/${repoOwner}/${repoName}.svg?style=flat-square)](https://codecov.io/gh/${repoOwner}/${repoName}) -[![CI](https://img.shields.io/github/actions/workflow/status/${repoOwner}/${repoName}/js-test-and-release.yml?branch=${defaultBranch}&style=flat-square)](https://github.com/${repoOwner}/${repoName}/actions/workflows/js-test-and-release.yml?query=branch%3A${defaultBranch}) +[![CI](https://img.shields.io/github/actions/workflow/status/${repoOwner}/${repoName}/${ciFile}?branch=${defaultBranch}&style=flat-square)](https://github.com/${repoOwner}/${repoName}/actions/workflows/${ciFile}?query=branch%3A${defaultBranch}) `, - multiformats: (repoOwner, repoName, defaultBranch) => ` + multiformats: (repoOwner, repoName, defaultBranch, ciFile) => ` [![multiformats.io](https://img.shields.io/badge/project-IPFS-blue.svg?style=flat-square)](http://multiformats.io) [![codecov](https://img.shields.io/codecov/c/github/${repoOwner}/${repoName}.svg?style=flat-square)](https://codecov.io/gh/${repoOwner}/${repoName}) -[![CI](https://img.shields.io/github/actions/workflow/status/${repoOwner}/${repoName}/js-test-and-release.yml?branch=${defaultBranch}&style=flat-square)](https://github.com/${repoOwner}/${repoName}/actions/workflows/js-test-and-release.yml?query=branch%3A${defaultBranch}) +[![CI](https://img.shields.io/github/actions/workflow/status/${repoOwner}/${repoName}/${ciFile}?branch=${defaultBranch}&style=flat-square)](https://github.com/${repoOwner}/${repoName}/actions/workflows/${ciFile}?query=branch%3A${defaultBranch}) `, - default: (repoOwner, repoName, defaultBranch) => ` + default: (repoOwner, repoName, defaultBranch, ciFile) => ` [![codecov](https://img.shields.io/codecov/c/github/${repoOwner}/${repoName}.svg?style=flat-square)](https://codecov.io/gh/${repoOwner}/${repoName}) -[![CI](https://img.shields.io/github/actions/workflow/status/${repoOwner}/${repoName}/js-test-and-release.yml?branch=${defaultBranch}&style=flat-square)](https://github.com/${repoOwner}/${repoName}/actions/workflows/js-test-and-release.yml?query=branch%3A${defaultBranch}) +[![CI](https://img.shields.io/github/actions/workflow/status/${repoOwner}/${repoName}/${ciFile}?branch=${defaultBranch}&style=flat-square)](https://github.com/${repoOwner}/${repoName}/actions/workflows/${ciFile}?query=branch%3A${defaultBranch}) ` } @@ -30,12 +30,13 @@ const BADGES = { * @param {string} repoOwner * @param {string} repoName * @param {string} defaultBranch + * @param {string} ciFile */ -export const HEADER = (pkg, repoOwner, repoName, defaultBranch) => { +export const HEADER = (pkg, repoOwner, repoName, defaultBranch, ciFile) => { return ` # ${pkg.name} -${(BADGES[repoOwner] ?? BADGES.default)(repoOwner, repoName, defaultBranch).trim()} +${(BADGES[repoOwner] ?? BADGES.default)(repoOwner, repoName, defaultBranch, ciFile).trim()} > ${pkg.description}