diff --git a/config/clients.config.json b/config/clients.config.json index d1a36c22091..2c3fbb3659a 100644 --- a/config/clients.config.json +++ b/config/clients.config.json @@ -1,6 +1,7 @@ { "java": { "folder": "clients/algoliasearch-client-java-2", + "mainGenerator": "javascript-search", "modelFolder": "algoliasearch-core/com/algolia/model", "customGenerator": "algolia-java", "tests": { @@ -10,6 +11,7 @@ }, "javascript": { "folder": "clients/algoliasearch-client-javascript", + "mainGenerator": "java-search", "modelFolder": "model", "tests": { "extension": ".test.ts", @@ -18,6 +20,7 @@ }, "php": { "folder": "clients/algoliasearch-client-php", + "mainGenerator": "php-search", "modelFolder": "lib/Model" } } diff --git a/scripts/common.ts b/scripts/common.ts index c5a517cdc2b..95a6dfeaaa8 100644 --- a/scripts/common.ts +++ b/scripts/common.ts @@ -40,6 +40,10 @@ Object.entries(openapitools['generator-cli'].generators).forEach( } ); +export function getPackageVersion(generator: string): string { + return GENERATORS[generator].additionalProperties.packageVersion; +} + export const LANGUAGES = [ ...new Set(Object.values(GENERATORS).map((gen) => gen.language)), ]; diff --git a/scripts/release/__tests__/create-release-issue.test.ts b/scripts/release/__tests__/create-release-issue.test.ts index 604c711f17d..b779e65121d 100644 --- a/scripts/release/__tests__/create-release-issue.test.ts +++ b/scripts/release/__tests__/create-release-issue.test.ts @@ -32,21 +32,21 @@ describe('create release issue', () => { getVersionChangesText({ javascript: { current: '0.0.1', - next: '0.0.2', + releaseType: 'patch', }, php: { current: '0.0.1', - next: '0.0.2', + releaseType: 'patch', }, java: { current: '0.0.1', - next: '0.0.2', + releaseType: 'patch', }, }) ).toMatchInlineSnapshot(` - "- [x] javascript: v0.0.1 -> v0.0.2 - - [x] java: v0.0.1 -> v0.0.2 - - [x] php: v0.0.1 -> v0.0.2" + "- [x] javascript: v0.0.1 -> \`patch\` _(e.g. v0.0.2)_ + - [x] java: v0.0.1 -> \`patch\` _(e.g. v0.0.2)_ + - [x] php: v0.0.1 -> \`patch\` _(e.g. v0.0.2)_" `); }); @@ -55,21 +55,21 @@ describe('create release issue', () => { getVersionChangesText({ javascript: { current: '0.0.1', - next: '0.0.2', + releaseType: 'patch', }, php: { current: '0.0.1', - next: '0.0.1', + releaseType: null, noCommit: true, }, java: { current: '0.0.1', - next: '0.0.2', + releaseType: 'patch', }, }) ).toMatchInlineSnapshot(` - "- [x] javascript: v0.0.1 -> v0.0.2 - - [x] java: v0.0.1 -> v0.0.2 + "- [x] javascript: v0.0.1 -> \`patch\` _(e.g. v0.0.2)_ + - [x] java: v0.0.1 -> \`patch\` _(e.g. v0.0.2)_ - ~php: v0.0.1 (no commit)~" `); }); @@ -79,23 +79,23 @@ describe('create release issue', () => { getVersionChangesText({ javascript: { current: '0.0.1', - next: '0.0.2', + releaseType: 'patch', }, php: { current: '0.0.1', - next: '0.0.1', + releaseType: 'minor', }, java: { current: '0.0.1', - next: '0.0.2', + releaseType: 'patch', skipRelease: true, }, }) ).toMatchInlineSnapshot(` - "- [x] javascript: v0.0.1 -> v0.0.2 - - [ ] java: v0.0.1 -> v0.0.2 + "- [x] javascript: v0.0.1 -> \`patch\` _(e.g. v0.0.2)_ + - [ ] java: v0.0.1 -> \`patch\` _(e.g. v0.0.2)_ - No \`feat\` or \`fix\` commit, thus unchecked by default. - - [x] php: v0.0.1 -> v0.0.1" + - [x] php: v0.0.1 -> \`minor\` _(e.g. v0.1.0)_" `); }); @@ -123,7 +123,7 @@ describe('create release issue', () => { ], }); - expect(versions.javascript.next).toEqual('1.0.0'); + expect(versions.javascript.releaseType).toEqual('major'); }); it('bumps minor version for feat', () => { @@ -150,7 +150,7 @@ describe('create release issue', () => { ], }); - expect(versions.php.next).toEqual('0.1.0'); + expect(versions.php.releaseType).toEqual('minor'); }); it('bumps patch version for fix', () => { @@ -177,7 +177,7 @@ describe('create release issue', () => { ], }); - expect(versions.java.next).toEqual('0.0.2'); + expect(versions.java.releaseType).toEqual('patch'); }); it('marks noCommit for languages without any commit', () => { diff --git a/scripts/release/__tests__/process-release.test.ts b/scripts/release/__tests__/process-release.test.ts index 2f174f234d8..066d3a1e0f0 100644 --- a/scripts/release/__tests__/process-release.test.ts +++ b/scripts/release/__tests__/process-release.test.ts @@ -1,20 +1,22 @@ +import { getVersionChangesText } from '../create-release-issue'; import { getVersionsToRelease, getLangsToUpdateRepo } from '../process-release'; +import TEXT from '../text'; describe('process release', () => { it('gets versions to release', () => { const versions = getVersionsToRelease(` ## Version Changes - - [x] javascript: v1.0.0 -> v1.1.0 - - [x] php: v2.0.0 -> v2.0.1 - - [ ] java: v3.0.0 -> v3.0.1 + - [x] javascript: v1.0.0 -> \`minor\` (e.g. v1.1.0) + - [x] php: v2.0.0 -> \`patch\` (e.g. v2.0.1) + - [ ] java: v3.0.0 -> \`patch\` (e.g. v3.0.1) `); expect(Object.keys(versions)).toEqual(['javascript', 'php']); expect(versions.javascript.current).toEqual('1.0.0'); - expect(versions.javascript.next).toEqual('1.1.0'); + expect(versions.javascript.releaseType).toEqual('minor'); expect(versions.php.current).toEqual('2.0.0'); - expect(versions.php.next).toEqual('2.0.1'); + expect(versions.php.releaseType).toEqual('patch'); }); it('gets langs to update', () => { @@ -22,10 +24,44 @@ describe('process release', () => { getLangsToUpdateRepo(` ## Version Changes -- [ ] javascript: v1.0.0 -> v1.1.0 -- [x] php: v2.0.0 -> v2.0.1 -- [ ] java: v3.0.0 -> v3.0.1 +- [ ] javascript: v1.0.0 -> \`minor\` (e.g. v1.1.0) +- [x] php: v2.0.0 -> \`patch\` (e.g. v2.0.1) +- [ ] java: v3.0.0 -> \`patch\` (e.g. v3.0.1) `) ).toEqual(['javascript', 'java']); }); + + it('parses issue body correctly', () => { + // This test is a glue between create-release-issue and process-release. + const issueBody = [ + TEXT.versionChangeHeader, + getVersionChangesText({ + javascript: { + current: '0.0.1', + releaseType: 'patch', + }, + php: { + current: '0.0.1', + releaseType: 'minor', + }, + java: { + current: '0.0.1', + releaseType: 'patch', + skipRelease: true, + }, + }), + ].join('\n'); + + const versions = getVersionsToRelease(issueBody); + expect(versions).toEqual({ + javascript: expect.objectContaining({ + current: '0.0.1', + releaseType: 'patch', + }), + php: expect.objectContaining({ + current: '0.0.1', + releaseType: 'minor', + }), + }); + }); }); diff --git a/scripts/release/common.ts b/scripts/release/common.ts index 30b09087966..63ae2a586f8 100644 --- a/scripts/release/common.ts +++ b/scripts/release/common.ts @@ -1,3 +1,4 @@ +import clientsConfig from '../../config/clients.config.json'; import config from '../../config/release.config.json'; import { getGitHubUrl, run } from '../common'; @@ -5,6 +6,15 @@ export const RELEASED_TAG = config.releasedTag; export const MAIN_BRANCH = config.mainBranch; export const OWNER = config.owner; export const REPO = config.repo; +export const MAIN_GENERATOR = Object.keys(clientsConfig).reduce( + (mainGenerator: { [lang: string]: string }, lang: string) => { + return { + ...mainGenerator, + [lang]: clientsConfig[lang].mainGenerator, + }; + }, + {} +); export function getTargetBranch(language: string): string { return config.targetBranch[language] || config.defaultTargetBranch; diff --git a/scripts/release/create-release-issue.ts b/scripts/release/create-release-issue.ts index e50b4b2eba0..116809fae0e 100755 --- a/scripts/release/create-release-issue.ts +++ b/scripts/release/create-release-issue.ts @@ -3,41 +3,40 @@ import { Octokit } from '@octokit/rest'; import dotenv from 'dotenv'; import semver from 'semver'; -import { GENERATORS, LANGUAGES, ROOT_ENV_PATH, run } from '../common'; - -import { RELEASED_TAG, MAIN_BRANCH, OWNER, REPO } from './common'; +import { LANGUAGES, ROOT_ENV_PATH, run, getPackageVersion } from '../common'; +import type { Language } from '../types'; + +import { + RELEASED_TAG, + MAIN_BRANCH, + OWNER, + REPO, + MAIN_GENERATOR, +} from './common'; import TEXT from './text'; +import type { + Versions, + VersionsWithoutReleaseType, + PassedCommit, + Commit, +} from './types'; dotenv.config({ path: ROOT_ENV_PATH }); -type Version = { - current: string; - next?: string | null; - noCommit?: boolean; - skipRelease?: boolean; -}; - -type Versions = { - [lang: string]: Version; -}; - -function readVersions(): Versions { - const versions = {}; - - Object.values(GENERATORS).forEach((gen) => { - if (!versions[gen.language]) { - versions[gen.language] = { - current: gen.additionalProperties?.packageVersion, - next: undefined, - }; - } - }); - return versions; +function readVersions(): VersionsWithoutReleaseType { + return Object.keys(MAIN_GENERATOR).reduce((acc, lang) => { + return { + ...acc, + [lang]: { + current: getPackageVersion(lang), + }, + }; + }, {}); } export function getVersionChangesText(versions: Versions): string { return LANGUAGES.map((lang) => { - const { current, next, noCommit, skipRelease } = versions[lang]; + const { current, releaseType, noCommit, skipRelease } = versions[lang]; if (noCommit) { return `- ~${lang}: v${current} (${TEXT.noCommit})~`; @@ -47,9 +46,10 @@ export function getVersionChangesText(versions: Versions): string { return `- ~${lang}: (${TEXT.currentVersionNotFound})~`; } + const next = semver.inc(current, releaseType!); const checked = skipRelease ? ' ' : 'x'; return [ - `- [${checked}] ${lang}: v${current} -> v${next}`, + `- [${checked}] ${lang}: v${current} -> \`${releaseType}\` _(e.g. v${next})_`, skipRelease && TEXT.descriptionForSkippedLang, ] .filter(Boolean) @@ -57,19 +57,6 @@ export function getVersionChangesText(versions: Versions): string { }).join('\n'); } -type PassedCommit = { - hash: string; - type: string; - lang: string; - message: string; - raw: string; -}; - -type Commit = - | PassedCommit - | { error: 'missing-language-scope' } - | { error: 'unknown-language-scope' }; - export function parseCommit(commit: string): Commit { const hash = commit.slice(0, 7); let message = commit.slice(8); @@ -82,7 +69,7 @@ export function parseCommit(commit: string): Commit { } message = message.slice(message.indexOf(':') + 1).trim(); type = matchResult[1]; - const lang = matchResult[2]; + const lang = matchResult[2] as Language; if (!LANGUAGES.includes(lang)) { return { error: 'unknown-language-scope' }; @@ -97,54 +84,69 @@ export function parseCommit(commit: string): Commit { }; } +/* eslint-disable no-param-reassign */ export function decideReleaseStrategy({ versions, commits, }: { - versions: Versions; + versions: VersionsWithoutReleaseType; commits: PassedCommit[]; }): Versions { - const ret: Versions = { ...versions }; - - LANGUAGES.forEach((lang) => { - const commitsPerLang = commits.filter((commit) => commit.lang === lang); - const currentVersion = versions[lang].current; - - if (commitsPerLang.length === 0) { - ret[lang].next = currentVersion; - ret[lang].noCommit = true; - return; - } - - if (semver.prerelease(currentVersion)) { - // if version is like 0.1.2-beta.1, it increases to 0.1.2-beta.2, even if there's a breaking change. - ret[lang].next = semver.inc(currentVersion, 'prerelease'); - return; - } + return Object.entries(versions).reduce( + (versionsWithReleaseType: Versions, [lang, version]) => { + const commitsPerLang = commits.filter((commit) => commit.lang === lang); + const currentVersion = versions[lang].current; + + if (commitsPerLang.length === 0) { + versionsWithReleaseType[lang] = { + ...version, + noCommit: true, + releaseType: null, + }; + return versionsWithReleaseType; + } - if ( - commitsPerLang.some((commit) => - commit.message.includes('BREAKING CHANGE') - ) - ) { - ret[lang].next = semver.inc(currentVersion, 'major'); - return; - } + if (semver.prerelease(currentVersion)) { + // if version is like 0.1.2-beta.1, it increases to 0.1.2-beta.2, even if there's a breaking change. + versionsWithReleaseType[lang] = { + ...version, + releaseType: 'prerelease', + }; + return versionsWithReleaseType; + } - const commitTypes = new Set(commitsPerLang.map(({ type }) => type)); - if (commitTypes.has('feat')) { - ret[lang].next = semver.inc(currentVersion, 'minor'); - return; - } + if ( + commitsPerLang.some((commit) => + commit.message.includes('BREAKING CHANGE') + ) + ) { + versionsWithReleaseType[lang] = { + ...version, + releaseType: 'major', + }; + return versionsWithReleaseType; + } - ret[lang].next = semver.inc(currentVersion, 'patch'); - if (!commitTypes.has('fix')) { - ret[lang].skipRelease = true; - } - }); + const commitTypes = new Set(commitsPerLang.map(({ type }) => type)); + if (commitTypes.has('feat')) { + versionsWithReleaseType[lang] = { + ...version, + releaseType: 'minor', + }; + return versionsWithReleaseType; + } - return ret; + versionsWithReleaseType[lang] = { + ...version, + releaseType: 'patch', + ...(commitTypes.has('fix') ? undefined : { skipRelease: true }), + }; + return versionsWithReleaseType; + }, + {} + ); } +/* eslint-enable no-param-reassign */ async function createReleaseIssue(): Promise { if (!process.env.GITHUB_TOKEN) { @@ -241,6 +243,7 @@ async function createReleaseIssue(): Promise { TEXT.versionChangeHeader, versionChanges, TEXT.descriptionVersionChanges, + TEXT.indenpendentVersioning, TEXT.changelogHeader, TEXT.changelogDescription, changelogs, @@ -270,6 +273,7 @@ async function createReleaseIssue(): Promise { }); } +// JS version of `if __name__ == '__main__'` if (require.main === module) { createReleaseIssue(); } diff --git a/scripts/release/process-release.ts b/scripts/release/process-release.ts index ec7ead84fdd..3629963bd3e 100755 --- a/scripts/release/process-release.ts +++ b/scripts/release/process-release.ts @@ -3,6 +3,8 @@ import fsp from 'fs/promises'; import dotenv from 'dotenv'; import execa from 'execa'; +import semver from 'semver'; +import type { ReleaseType } from 'semver'; import openapitools from '../../openapitools.json'; import { @@ -24,9 +26,23 @@ import { cloneRepository, } from './common'; import TEXT from './text'; +import type { VersionsToRelease } from './types'; dotenv.config({ path: ROOT_ENV_PATH }); +type BeforeClientGenerationCommand = (params: { + releaseType: ReleaseType; + dir: string; +}) => Promise; + +const BEFORE_CLIENT_GENERATION: { + [lang: string]: BeforeClientGenerationCommand; +} = { + javascript: async ({ releaseType, dir }) => { + await run(`yarn release:bump ${releaseType}`, { cwd: dir }); + }, +}; + function getIssueBody(): string { return JSON.parse( execa.sync('curl', [ @@ -37,14 +53,6 @@ function getIssueBody(): string { ).body; } -type VersionsToRelease = { - [lang: string]: { - current: string; - next: string; - dateStamp: string; - }; -}; - function getDateStamp(): string { return new Date().toISOString().split('T')[0]; } @@ -56,14 +64,19 @@ export function getVersionsToRelease(issueBody: string): VersionsToRelease { getMarkdownSection(issueBody, TEXT.versionChangeHeader) .split('\n') .forEach((line) => { - const result = line.match(/- \[x\] (.+): v(.+) -> v(.+)/); + const result = line.match(/- \[x\] (.+): v(.+) -> `(.+)`/); if (!result) { return; } - const [, lang, current, next] = result; + const [, lang, current, releaseType] = result; + if (!['major', 'minor', 'patch', 'prerelease'].includes(releaseType)) { + throw new Error( + `\`${releaseType}\` is unknown release type. Allowed: major, minor, patch, prerelease` + ); + } versionsToRelease[lang] = { current, - next, + releaseType: releaseType as ReleaseType, dateStamp, }; }); @@ -75,7 +88,7 @@ export function getLangsToUpdateRepo(issueBody: string): string[] { return getMarkdownSection(issueBody, TEXT.versionChangeHeader) .split('\n') .map((line) => { - const result = line.match(/- \[ \] (.+): v(.+) -> v(.+)/); + const result = line.match(/- \[ \] (.+): v(.+) -> `(.+)`/); return result?.[1]; }) .filter(Boolean) as string[]; @@ -87,9 +100,19 @@ async function updateOpenApiTools( Object.keys(openapitools['generator-cli'].generators).forEach((client) => { const lang = client.split('-')[0]; if (versionsToRelease[lang]) { - openapitools['generator-cli'].generators[ - client - ].additionalProperties.packageVersion = versionsToRelease[lang].next; + const additionalProperties = + openapitools['generator-cli'].generators[client].additionalProperties; + + const newVersion = semver.inc( + additionalProperties.packageVersion, + versionsToRelease[lang].releaseType + ); + if (!newVersion) { + throw new Error( + `Failed to bump version ${additionalProperties.packageVersion} by ${versionsToRelease[lang].releaseType}.` + ); + } + additionalProperties.packageVersion = newVersion; } }); await fsp.writeFile( @@ -98,6 +121,40 @@ async function updateOpenApiTools( ); } +async function updateChangelog({ + lang, + issueBody, + current, + next, + dateStamp, + willReleaseLibrary, +}: { + lang: string; + issueBody: string; + current: string; + next: string; + dateStamp: string; + willReleaseLibrary: boolean; +}): Promise { + const changelogPath = toAbsolutePath( + `${getLanguageFolder(lang)}/CHANGELOG.md` + ); + const existingContent = (await exists(changelogPath)) + ? (await fsp.readFile(changelogPath)).toString() + : ''; + const changelogHeader = willReleaseLibrary + ? `## [v${next}](${getGitHubUrl(lang)}/compare/v${current}...v${next})` + : `## ${dateStamp}`; + const newChangelog = getMarkdownSection( + getMarkdownSection(issueBody, TEXT.changelogHeader), + `### ${lang}` + ); + await fsp.writeFile( + changelogPath, + [changelogHeader, newChangelog, existingContent].join('\n\n') + ); +} + async function processRelease(): Promise { if (!process.env.GITHUB_TOKEN) { throw new Error('Environment variable `GITHUB_TOKEN` does not exist.'); @@ -122,11 +179,6 @@ async function processRelease(): Promise { await updateOpenApiTools(versionsToRelease); - await configureGitHubAuthor(); - - // commit openapitools and changelogs - await run('git add openapitools.json'); - const langsToReleaseOrUpdate = [ ...Object.keys(versionsToRelease), ...langsToUpdateRepo, @@ -136,32 +188,36 @@ async function processRelease(): Promise { Boolean(versionsToRelease[lang]); for (const lang of langsToReleaseOrUpdate) { - // prepare the submodule + const { current, releaseType, dateStamp } = versionsToRelease[lang]; + /* + About bumping versions of JS clients: + + There are generated clients in JS repo, and non-generated clients like `algoliasearch`, `client-common`, etc. + Now that the versions of generated clients are updated in `openapitools.json`, + the generation output will have correct new versions. + + However, we need to manually update versions of the non-generated (a.k.a. manually written) clients. + In order to do that, we run `yarn release:bump ` in this monorepo first. + It will update the versions of the non-generated clients which exists in this monorepo. + After that, we generate clients with new versions. And then, we copy all of them over to JS repository. + */ + await BEFORE_CLIENT_GENERATION[lang]?.({ + releaseType, + dir: toAbsolutePath(getLanguageFolder(lang)), + }); + console.log(`Generating ${lang} client(s)...`); console.log(await run(`yarn cli generate ${lang}`)); - const { current, next, dateStamp } = versionsToRelease[lang]; - - // update changelog - const changelogPath = toAbsolutePath( - `${getLanguageFolder(lang)}/CHANGELOG.md` - ); - const existingContent = (await exists(changelogPath)) - ? (await fsp.readFile(changelogPath)).toString() - : ''; - const changelogHeader = willReleaseLibrary(lang) - ? `## [v${next}](${getGitHubUrl(lang)}/compare/v${current}...v${next})` - : `## ${dateStamp}`; - const newChangelog = getMarkdownSection( - getMarkdownSection(issueBody, TEXT.changelogHeader), - `### ${lang}` - ); - await fsp.writeFile( - changelogPath, - [changelogHeader, newChangelog, existingContent].join('\n\n') - ); - - await run(`git add ${changelogPath}`); + const next = semver.inc(current, releaseType); + await updateChangelog({ + lang, + issueBody, + current, + next: next!, + dateStamp, + willReleaseLibrary: willReleaseLibrary(lang), + }); } // We push commits to each repository AFTER all the generations are done. @@ -179,7 +235,8 @@ async function processRelease(): Promise { await configureGitHubAuthor(tempGitDir); await run(`git add .`, { cwd: tempGitDir }); - const { next, dateStamp } = versionsToRelease[lang]; + const { current, dateStamp, releaseType } = versionsToRelease[lang]; + const next = semver.inc(current, releaseType); if (willReleaseLibrary(lang)) { await gitCommit({ @@ -200,6 +257,9 @@ async function processRelease(): Promise { } // Commit and push from the monorepo level. + await configureGitHubAuthor(); + await run(`git add .`); + await execa('git', ['commit', '-m', `chore: release ${getDateStamp()}`]); await gitCommit({ message: `chore: release ${getDateStamp()}`, }); @@ -215,6 +275,7 @@ async function processRelease(): Promise { await run(`git push --tags`); } +// JS version of `if __name__ == '__main__'` if (require.main === module) { processRelease(); } diff --git a/scripts/release/text.ts b/scripts/release/text.ts index 4a2a2d6b402..c6f2d9ee899 100644 --- a/scripts/release/text.ts +++ b/scripts/release/text.ts @@ -11,6 +11,23 @@ export default { `**Un-checked** → Update repository.`, `**Line removed** → Do nothing.`, ].join('\n'), + indenpendentVersioning: ` + + The JavaScript repository consists of several packages with independent versioning. Release type is applied to each version. + +
+ For example, if the release type is \`patch\`, + + * \`algoliasearch\`@5.0.0 -> 5.0.1 + * \`@algolia/client-search\`@5.0.0 -> 5.0.1 + * \`@algolia/client-abtesting\`@5.0.0 -> 5.0.1 + * ... + * \`@algolia/client-predict\`@0.0.1 -> 0.0.2 + * ... + * \`@algolia/requester-browser-xhr\`@0.0.5 -> 0.0.6. +
+
+ `, descriptionForSkippedLang: ` - No \`feat\` or \`fix\` commit, thus unchecked by default.`, changelogHeader: `## CHANGELOG`, diff --git a/scripts/release/types.ts b/scripts/release/types.ts new file mode 100644 index 00000000000..f05a7bd9da2 --- /dev/null +++ b/scripts/release/types.ts @@ -0,0 +1,39 @@ +import type { ReleaseType } from 'semver'; + +import type { Language } from '../types'; + +export type Version = { + current: string; + releaseType: ReleaseType | null; + skipRelease?: boolean; + noCommit?: boolean; +}; + +export type Versions = { + [lang: string]: Version; +}; + +export type VersionsWithoutReleaseType = { + [lang: string]: Omit; +}; + +export type PassedCommit = { + hash: string; + type: string; + lang: Language; + message: string; + raw: string; +}; + +export type Commit = + | PassedCommit + | { error: 'missing-language-scope' } + | { error: 'unknown-language-scope' }; + +export type VersionsToRelease = { + [lang: string]: { + current: string; + releaseType: ReleaseType; + dateStamp: string; + }; +}; diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json index eacb895f563..25f5d607f0e 100644 --- a/scripts/tsconfig.json +++ b/scripts/tsconfig.json @@ -6,5 +6,5 @@ "outDir": "dist" }, "include": ["**/*.ts"], - "exclude": ["dist", "*.json", "node_modules"] + "exclude": ["dist", "*.json", "node_modules", "**/*.test.ts"] } diff --git a/scripts/types.ts b/scripts/types.ts index 22a7720e73c..3b2382a58ea 100644 --- a/scripts/types.ts +++ b/scripts/types.ts @@ -1,3 +1,5 @@ +import type config from '../config/clients.config.json'; + export type Generator = Record & { language: string; client: string; @@ -13,3 +15,5 @@ export type RunOptions = { verbose?: boolean; cwd?: string; }; + +export type Language = keyof typeof config;