From 58acf1dd3ed2a2276db709293663df53401a8692 Mon Sep 17 00:00:00 2001 From: Irshad Ahmad Date: Mon, 22 Jan 2024 13:43:06 +0530 Subject: [PATCH 01/12] Simplify bundle command and schema --- tools/wpdev/src/commands/bundle.ts | 53 +++++++++++------------------- tools/wpdev/src/utils/schema.ts | 5 --- 2 files changed, 19 insertions(+), 39 deletions(-) diff --git a/tools/wpdev/src/commands/bundle.ts b/tools/wpdev/src/commands/bundle.ts index ec5ad21a..ff7d84cd 100644 --- a/tools/wpdev/src/commands/bundle.ts +++ b/tools/wpdev/src/commands/bundle.ts @@ -29,7 +29,8 @@ export default class Bundle extends WithProjects { static flags = { 'out-dir': Flags.string({ char: 'd', - description: 'Path to the output directory. Defaults to "dist/{slug}".', + description: 'Path to the output directory. Defaults to "dist".', + default: 'dist', }), 'update-source-files': Flags.boolean({ char: 'u', @@ -87,8 +88,6 @@ export default class Bundle extends WithProjects { ...WithProjects.args, }; - protected destPlaceholder = '{slug}'; - public async run(): Promise { const tasks = new Listr([], { concurrent: true, @@ -121,18 +120,14 @@ export default class Bundle extends WithProjects { } } - getOutputDir() { - if (this.flags['out-dir']) { - return this.projects.size === 1 - ? this.flags['out-dir'] - : path.join(this.flags['out-dir'], this.destPlaceholder); - } + getOutputDir(project: WPProject) { + const baseOutDir = this.flags['out-dir'] || 'dist'; - return `dist/${this.destPlaceholder}`; - } + if (this.cliConfig.operationMode !== 'wp-monorepo') { + return baseOutDir; + } - parseOutputDir(outDir: string, slug: string) { - return outDir.replace(this.destPlaceholder, slug); + return path.join(baseOutDir, project.relativeDir); } getVersion(project: WPProject, task: TaskWrapper) { @@ -170,7 +165,7 @@ export default class Bundle extends WithProjects { const { projectInfo, bundle } = await getProjectConfig(project, version); - const outDir = this.parseOutputDir(this.getOutputDir(), projectInfo.slug); + const outDir = this.getOutputDir(project); const canChangeSourceFiles = this.flags['update-source-files']; @@ -209,17 +204,12 @@ export default class Bundle extends WithProjects { return task.skip(); } - const { - sourceDir, - destDir, - ignore = getDistIgnorePattern(project.dir), - } = bundle.tasks.copyFilesBefore; + const { sourceDir, ignore = getDistIgnorePattern(project.dir) } = + bundle.tasks.copyFilesBefore; - return await copyDir( - path.join(project.dir, sourceDir), - this.parseOutputDir(destDir, projectInfo.slug), - { ignore }, - ); + return await copyDir(path.join(project.dir, sourceDir), outDir, { + ignore, + }); }, }, { @@ -345,17 +335,12 @@ export default class Bundle extends WithProjects { return task.skip(); } - const { - sourceDir, - destDir, - ignore = getDistIgnorePattern(project.dir), - } = bundle.tasks.copyFilesAfter; + const { sourceDir, ignore = getDistIgnorePattern(project.dir) } = + bundle.tasks.copyFilesAfter; - return await copyDir( - path.join(project.dir, sourceDir), - this.parseOutputDir(destDir, projectInfo.slug), - { ignore }, - ); + return await copyDir(path.join(project.dir, sourceDir), outDir, { + ignore, + }); }, }, { diff --git a/tools/wpdev/src/utils/schema.ts b/tools/wpdev/src/utils/schema.ts index b2d3b415..c6e3ab2a 100644 --- a/tools/wpdev/src/utils/schema.ts +++ b/tools/wpdev/src/utils/schema.ts @@ -16,11 +16,6 @@ const copyFilesData = z.object({ .optional() .default('src') .describe('The source directory.'), - destDir: z - .string() - .optional() - .default('dist/{slug}') - .describe('The destination directory. Defaults to dist/{slug}.'), ignore: targetFilesSchema.shape.ignore, }); From 4def5a350cbb9d28261d7333a75c9370aabf8ad6 Mon Sep 17 00:00:00 2001 From: Irshad Ahmad Date: Mon, 22 Jan 2024 13:43:27 +0530 Subject: [PATCH 02/12] Enable support for mu and premium plugins --- tools/wpdev/src/utils/tools.ts | 4 ++-- tools/wpdev/src/utils/wp-monorepo.ts | 35 ++++++++++++++++++++-------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/tools/wpdev/src/utils/tools.ts b/tools/wpdev/src/utils/tools.ts index 92540637..77c24b32 100644 --- a/tools/wpdev/src/utils/tools.ts +++ b/tools/wpdev/src/utils/tools.ts @@ -14,14 +14,14 @@ export const UserConfigSchema = z .default('standalone') .describe('Whether this is a wp-monorepo or standalone project.'), projectTypes: z - .array(z.enum(['plugins', 'themes'])) + .array(z.enum(['plugins', 'themes', 'mu-plugins'])) .optional() .default(['plugins', 'themes']) .describe( 'The project types managed by this monorepo. Only used in wp-monorepo mode.', ), belongsTo: z - .enum(['plugins', 'themes']) + .enum(['plugins', 'themes', 'mu-plugins']) .optional() .describe( 'The project type this project belongs to. Used for individual packages in a monorepo or for standalone projects.', diff --git a/tools/wpdev/src/utils/wp-monorepo.ts b/tools/wpdev/src/utils/wp-monorepo.ts index c00d0eaa..f4b77c27 100644 --- a/tools/wpdev/src/utils/wp-monorepo.ts +++ b/tools/wpdev/src/utils/wp-monorepo.ts @@ -37,10 +37,14 @@ export class WPMonorepo { * Returns an array of connected project names as defined in the CONNECTED_PROJECTS env var. */ getConnectedProjectsNames() { - return (process.env.CONNECTED_PROJECTS || '') - .split(',') - .map((project) => project.trim()) - .filter(Boolean); + return [ + ...new Set( + (process.env.CONNECTED_PROJECTS || '') + .split(',') + .map((project) => project.trim()) + .filter(Boolean), + ), + ]; } getProjectStatus(project: WPProject): ProjectStatus { @@ -48,6 +52,18 @@ export class WPMonorepo { if (this.getConnectedProjectsNames().includes(project.packageJson.name)) { return 'connected'; } + + // If the project is in the "premium" folder + // e.g. "premium/plugins/wptelegram-pro" + const isPremium = project.relativeDir.startsWith( + path.normalize('premium/'), + ); + + // If the project is premium, it should be treated as connected + if (isPremium) { + return 'connected'; + } + try { // If `git check-ignore ` succeeds, it means the path is ignored execaSync('git', ['check-ignore', project.dir]); @@ -74,13 +90,12 @@ export class WPMonorepo { projectType = pkg.packageJson.wpdev?.belongsTo; } } else { - // If "belongsTo" is not defined, we can use the package containing folder name to determine the project type + // If "belongsTo" is not defined, we can use the package's parent folder name to determine the project type // For example `relativeDir: 'plugins/wptelegram-widget'` - for (const _type of projectTypes) { - if (pkg.relativeDir.startsWith(_type)) { - projectType = _type; - break; - } + const parentDir = path.basename(path.dirname(pkg.dir)) as ProjectType; + + if (projectTypes.includes(parentDir)) { + projectType = parentDir; } } From 423e785ec3f94d3b6a9ce9ab1eaf1e2529bac563 Mon Sep 17 00:00:00 2001 From: Irshad Ahmad Date: Mon, 22 Jan 2024 13:43:43 +0530 Subject: [PATCH 03/12] Update config --- .github/workflows/deploy.yml | 4 ++-- pnpm-hashed.lock | 2 +- pnpm-workspace.yaml | 13 +++++++------ 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index be092276..6d2f50ff 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -43,8 +43,8 @@ jobs: VERSION: ${{ fromJson(needs.details.outputs.result).version }} BUILD_DIR: "dist/${{ fromJson(needs.details.outputs.result).name }}" ASSETS_DIR: "${{ fromJson(needs.details.outputs.result).path }}/.wordpress-org" - SVN_USERNAME: ${{ secrets.SVN_USERNAME }}test - SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}test + SVN_USERNAME: ${{ secrets.SVN_USERNAME }} + SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }} - name: Copy README.md to dist run: | diff --git a/pnpm-hashed.lock b/pnpm-hashed.lock index e57435c2..5993ef4f 100644 --- a/pnpm-hashed.lock +++ b/pnpm-hashed.lock @@ -1 +1 @@ -0380af5cd2a85662ece79600ffb61f58d0f415c9 \ No newline at end of file +f1b3f5ae40b67e51ebb53015bc016524ceb695e0 \ No newline at end of file diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index bc4b8647..0c5acf1d 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,7 +1,8 @@ packages: - - 'packages/js/*' - - '!packages/js/shared' - - 'packages/js/shared/*' - - 'packages/php/*' # Just for running PHP tests via pnpm - - 'plugins/*' - - 'tools/*' + - "packages/js/*" + - "!packages/js/shared" + - "packages/js/shared/*" + - "packages/php/*" # Just for running PHP tests via pnpm + - "plugins/*" + # - "premium/plugins/*" + - "tools/*" From 4b489f32b7e6d34c6d94eb96a410f36f7443df00 Mon Sep 17 00:00:00 2001 From: Irshad Ahmad Date: Mon, 22 Jan 2024 17:59:59 +0530 Subject: [PATCH 04/12] Add project-info command --- tools/wpdev/src/commands/project-info.ts | 43 ++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tools/wpdev/src/commands/project-info.ts diff --git a/tools/wpdev/src/commands/project-info.ts b/tools/wpdev/src/commands/project-info.ts new file mode 100644 index 00000000..b5e6fc7b --- /dev/null +++ b/tools/wpdev/src/commands/project-info.ts @@ -0,0 +1,43 @@ +import { Flags } from '@oclif/core'; +import chalk from 'chalk'; +import { WithProjects } from '../base-commands/WithProjects.js'; + +export default class ProjectInfo extends WithProjects { + static description = 'Get the project info as JSON.'; + + static flags = { + pretty: Flags.boolean({ + description: 'Pretty print the JSON output.', + }), + }; + + static args = { + ...WithProjects.args, + }; + + public async run(): Promise { + try { + const projects = [...this.projects].map( + ([name, { relativeDir, dir, packageJson }]) => { + return { + name, + version: packageJson.version, + relativeDir, + dir, + wpdev: packageJson.wpdev, + }; + }, + ); + + const result = + this.cliConfig.operationMode !== 'wp-monorepo' ? projects[0] : projects; + + this.flags.pretty + ? this.logJson(result) + : this.log(JSON.stringify(result)); + } catch (error) { + this.log(chalk.red((error as { message: string }).message)); + process.exitCode = 1; + } + } +} From 2a3aea39a8e1fc7c6f69d1239d24e419ed99d7b7 Mon Sep 17 00:00:00 2001 From: Irshad Ahmad Date: Mon, 22 Jan 2024 18:00:11 +0530 Subject: [PATCH 05/12] Clean up --- tools/wpdev/src/utils/monorepo.ts | 7 ------- tools/wpdev/src/utils/wp-monorepo.ts | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 tools/wpdev/src/utils/monorepo.ts diff --git a/tools/wpdev/src/utils/monorepo.ts b/tools/wpdev/src/utils/monorepo.ts deleted file mode 100644 index a0d95b69..00000000 --- a/tools/wpdev/src/utils/monorepo.ts +++ /dev/null @@ -1,7 +0,0 @@ -import path from 'node:path'; -import { fileURLToPath } from 'node:url'; - -const __filename = fileURLToPath(import.meta.url); -const __dirname = path.dirname(__filename); - -export const ROOT_DIR = path.resolve(__dirname, '../../../../'); diff --git a/tools/wpdev/src/utils/wp-monorepo.ts b/tools/wpdev/src/utils/wp-monorepo.ts index f4b77c27..0982c300 100644 --- a/tools/wpdev/src/utils/wp-monorepo.ts +++ b/tools/wpdev/src/utils/wp-monorepo.ts @@ -156,7 +156,7 @@ export class WPMonorepo { projects.set(projectName, project); } else if (throwIfNotFound) { throw new Error( - `Invalid project: Could not find a package with name: "${projectName}"`, + `Invalid project: Could not find a WordPress project with name: "${projectName}"`, ); } } From d43b15f90cf821f7a9aac910bfe01a05be2b1b25 Mon Sep 17 00:00:00 2001 From: Irshad Ahmad Date: Mon, 22 Jan 2024 18:00:39 +0530 Subject: [PATCH 06/12] Use the updated CLI in deployment --- .github/workflows/deploy.yml | 60 +++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6d2f50ff..6fb206c4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -30,7 +30,7 @@ jobs: uses: AButler/upload-release-assets@v3.0 with: # e.g. dist/plugin-name-1.0.0.zip - files: "dist/${{ fromJson(needs.details.outputs.result).name }}-${{ fromJson(needs.details.outputs.result).version }}.zip" + files: "dist/${{ fromJson(needs.details.outputs.result).relativeDir }}-${{ fromJson(needs.details.outputs.result).version }}.zip" repo-token: ${{ secrets.GITHUB_TOKEN }} - name: Deploy to WordPress.org @@ -41,19 +41,19 @@ jobs: env: SLUG: ${{ fromJson(needs.details.outputs.result).name }} VERSION: ${{ fromJson(needs.details.outputs.result).version }} - BUILD_DIR: "dist/${{ fromJson(needs.details.outputs.result).name }}" - ASSETS_DIR: "${{ fromJson(needs.details.outputs.result).path }}/.wordpress-org" - SVN_USERNAME: ${{ secrets.SVN_USERNAME }} - SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }} + BUILD_DIR: "dist/${{ fromJson(needs.details.outputs.result).relativeDir }}" + ASSETS_DIR: "${{ fromJson(needs.details.outputs.result).relativeDir }}/.wordpress-org" + SVN_USERNAME: ${{ secrets.SVN_USERNAME || 'test' }} + SVN_PASSWORD: ${{ secrets.SVN_PASSWORD || 'test' }} - name: Copy README.md to dist run: | - cp ${{ fromJson(needs.details.outputs.result).path }}/README.md dist/${{ fromJson(needs.details.outputs.result).name }}/README.md + cp ${{ fromJson(needs.details.outputs.result).relativeDir }}/README.md dist/${{ fromJson(needs.details.outputs.result).relativeDir }}/README.md - name: Deploy to repo uses: manzoorwanijk/action-deploy-to-repo@v3 with: - src_dir: dist/${{ fromJson(needs.details.outputs.result).name }} + src_dir: dist/${{ fromJson(needs.details.outputs.result).relativeDir }} target_repo: ${{ github.repository_owner }}/${{ fromJson(needs.details.outputs.result).name }} target_dir: "." target_branch: main @@ -67,7 +67,21 @@ jobs: outputs: result: ${{ steps.details.outputs.result }} steps: - - name: Get release details + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Environment + uses: ./actions/setup + with: + lockfile: pnpm-hashed.lock + enable-wireit-cache: true + + - name: List projects + id: projects + run: | + echo "result=$(pnpm wpdev project-info --all)" >> $GITHUB_OUTPUT + + - name: Get details uses: actions/github-script@v7 id: details with: @@ -77,34 +91,22 @@ jobs: const result = '${{ github.event.release.tag_name }}'.match(tagRegex); if (!result) { - throw new Error('Invalid tag name: ${{ github.event.release.tag_name }}'); + console.warn('Invalid tag name: "${{ github.event.release.tag_name }}"'); + + return { shouldDeploy: false }; } const { name, version } = result.groups; - const plugins = [ - 'wptelegram', - 'wptelegram-comments', - 'wptelegram-login', - 'wptelegram-widget', - ]; - - const themes = []; - - const toDeploy = [...plugins, ...themes]; - - const belongsTo = plugins.includes(name) - ? 'plugins' - : themes.includes(name) - ? 'themes' - : ''; + const projects = ${{ steps.projects.outputs.result }}; - const path = [belongsTo, name].filter(Boolean).join('/'); + const project = projects.find(project => project.name === name); - const shouldDeploy = toDeploy.includes(name); + const shouldDeploy = Boolean(project); - return { name, version, path, shouldDeploy }; + // User the version from the tag to ensure we're deploying the correct version + return { ...project, name, version, shouldDeploy }; - name: Print details run: | - echo "Package details: ${{ steps.details.outputs.result }}" + echo "Details: ${{ steps.details.outputs.result }}" From 3d37b2e241933fc8553be8f84695705073785cdf Mon Sep 17 00:00:00 2001 From: Irshad Ahmad Date: Mon, 22 Jan 2024 18:00:47 +0530 Subject: [PATCH 07/12] Clean up --- actions/setup/action.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/actions/setup/action.yml b/actions/setup/action.yml index 18a58f6f..30abf80a 100644 --- a/actions/setup/action.yml +++ b/actions/setup/action.yml @@ -3,32 +3,26 @@ description: "This action checks out the commit, sets up Node, pnpm, PHP, WP CLI author: "wpsocio" inputs: cache-key: - required: false description: "Cache busting key. If this changes, the cache will be busted." default: "1" node-version: - required: false description: "The version of Node to use." default: "lts/*" php-version: - required: false description: "The version of PHP to use." default: "8" pnpm-version: - required: false description: "The version of pnpm to use." default: "latest" lockfile: - required: false description: "The lockfile to use." default: "pnpm-lock.yaml" enable-wireit-cache: - required: false description: "Enable Wireit cache." default: "false" From c3c4123d8b39607c8ecb2b83a980485060e6be40 Mon Sep 17 00:00:00 2001 From: Irshad Ahmad Date: Mon, 22 Jan 2024 22:20:15 +0530 Subject: [PATCH 08/12] Update README.txt --- plugins/wptelegram-comments/src/{README.txt => readme.txt} | 4 +++- plugins/wptelegram-login/src/{README.txt => readme.txt} | 2 +- plugins/wptelegram-widget/src/{README.txt => readme.txt} | 2 +- plugins/wptelegram/src/{README.txt => readme.txt} | 2 ++ 4 files changed, 7 insertions(+), 3 deletions(-) rename plugins/wptelegram-comments/src/{README.txt => readme.txt} (96%) rename plugins/wptelegram-login/src/{README.txt => readme.txt} (98%) rename plugins/wptelegram-widget/src/{README.txt => readme.txt} (98%) rename plugins/wptelegram/src/{README.txt => readme.txt} (99%) diff --git a/plugins/wptelegram-comments/src/README.txt b/plugins/wptelegram-comments/src/readme.txt similarity index 96% rename from plugins/wptelegram-comments/src/README.txt rename to plugins/wptelegram-comments/src/readme.txt index 16b801fa..0c15672a 100644 --- a/plugins/wptelegram-comments/src/README.txt +++ b/plugins/wptelegram-comments/src/readme.txt @@ -98,4 +98,6 @@ For rules, see the pinned message. No spam please. * Minor fixes = 1.0.0 = -* Initial Release \ No newline at end of file +* Initial Release + +[See full changelog](https://github.com/wpsocio/wptelegram-comments/blob/main/CHANGELOG.md) diff --git a/plugins/wptelegram-login/src/README.txt b/plugins/wptelegram-login/src/readme.txt similarity index 98% rename from plugins/wptelegram-login/src/README.txt rename to plugins/wptelegram-login/src/readme.txt index af9a725d..a0cef9bf 100644 --- a/plugins/wptelegram-login/src/README.txt +++ b/plugins/wptelegram-login/src/readme.txt @@ -174,4 +174,4 @@ Follow the instructions given on the settings page. You need to send `/setdomain = 1.10.0 = - Added support for Telegram Web App data authorization -== Upgrade Notice == \ No newline at end of file +[See full changelog](https://github.com/wpsocio/wptelegram-login/blob/main/CHANGELOG.md) diff --git a/plugins/wptelegram-widget/src/README.txt b/plugins/wptelegram-widget/src/readme.txt similarity index 98% rename from plugins/wptelegram-widget/src/README.txt rename to plugins/wptelegram-widget/src/readme.txt index f09235eb..225f5f81 100644 --- a/plugins/wptelegram-widget/src/README.txt +++ b/plugins/wptelegram-widget/src/readme.txt @@ -235,4 +235,4 @@ Legacy Widget does not show the old messages. you need to post something new int - Refreshed and improved the UI - Improved names for hooks and shortcodes -== Upgrade Notice == \ No newline at end of file +[See full changelog](https://github.com/wpsocio/wptelegram-widget/blob/main/CHANGELOG.md) diff --git a/plugins/wptelegram/src/README.txt b/plugins/wptelegram/src/readme.txt similarity index 99% rename from plugins/wptelegram/src/README.txt rename to plugins/wptelegram/src/readme.txt index 99383af9..26360abf 100644 --- a/plugins/wptelegram/src/README.txt +++ b/plugins/wptelegram/src/readme.txt @@ -259,3 +259,5 @@ Yes, all you need to do is to setup **Private Notifications** module and use the - Removed support for Markdown formatting in favour of better HTML formatting - Fixed the image not being sent "After the text" when "Send files by URL" is disabled - Fixed the issue of messages not being sent when the markup is not valid + +[See full changelog](https://github.com/wpsocio/wptelegram/blob/main/CHANGELOG.md) From 1e6362667866cf8253721d006a4a554397cf42a0 Mon Sep 17 00:00:00 2001 From: Irshad Ahmad Date: Tue, 23 Jan 2024 10:38:12 +0530 Subject: [PATCH 09/12] Add update changelog task --- plugins/wpdev.base.project.js | 3 + tools/wpdev/src/base-commands/WithProjects.ts | 15 ++- tools/wpdev/src/commands/bundle.ts | 21 ++++ tools/wpdev/src/utils/changelog.ts | 111 +++++++++++------- tools/wpdev/src/utils/misc.ts | 5 + tools/wpdev/src/utils/schema.ts | 7 ++ tools/wpdev/src/utils/wp-monorepo.ts | 20 +--- 7 files changed, 116 insertions(+), 66 deletions(-) diff --git a/plugins/wpdev.base.project.js b/plugins/wpdev.base.project.js index c6fc204e..55fb1a45 100644 --- a/plugins/wpdev.base.project.js +++ b/plugins/wpdev.base.project.js @@ -48,6 +48,9 @@ export const getBundleConfig = ({ slug, key, version, textDomain }) => { ], }, ], + updateChangelog: { + readmeTxtFile: 'src/readme.txt', + }, generatePot: { source: 'src', textDomain, diff --git a/tools/wpdev/src/base-commands/WithProjects.ts b/tools/wpdev/src/base-commands/WithProjects.ts index e690f834..26d6ab6a 100644 --- a/tools/wpdev/src/base-commands/WithProjects.ts +++ b/tools/wpdev/src/base-commands/WithProjects.ts @@ -29,9 +29,14 @@ export abstract class WithProjects< all: Flags.boolean({ description: 'Target all projects in monorepo.', }), - 'from-release': Flags.string({ + 'from-changeset': Flags.boolean({ + description: 'Target projects in monorepo from changesets.', + dependsOn: ['changeset-json'], + }), + 'changeset-json': Flags.file({ description: - 'Target projects in monorepo that are to be released next. Pass the {filePath} given to `changset status --output={filePath}`', + 'Path to the changeset status JSON file. Pass the {filePath} given to `changset status --output={filePath}`', + default: '', }), }; @@ -93,11 +98,11 @@ export abstract class WithProjects< this.args = args as TArgs; if (this.cliConfig.operationMode === 'wp-monorepo') { - if (flags['from-release']) { + if (this.flags['from-changeset']) { this.projects = this.wpMonorepo.getProjectsToRelease( - flags['from-release'], + this.flags['changeset-json'], ); - } else if (flags.all) { + } else if (this.flags.all) { this.projects = this.wpMonorepo.getManagedProjects(); } else if (argv.length) { this.projects = this.wpMonorepo.getProjectsByName( diff --git a/tools/wpdev/src/commands/bundle.ts b/tools/wpdev/src/commands/bundle.ts index ff7d84cd..8359c9d1 100644 --- a/tools/wpdev/src/commands/bundle.ts +++ b/tools/wpdev/src/commands/bundle.ts @@ -3,6 +3,7 @@ import { Flags } from '@oclif/core'; import chalk from 'chalk'; import { Listr, ListrTask } from 'listr2'; import { WithProjects } from '../base-commands/WithProjects.js'; +import { updateChangelog } from '../utils/changelog.js'; import { generatePotFile, makeMoFiles, @@ -212,6 +213,26 @@ export default class Bundle extends WithProjects { }); }, }, + { + title: 'Update changelog', + task: async (_, task) => { + if ( + !bundle.tasks.updateChangelog || + !this.flags['changeset-json'] + ) { + return task.skip(); + } + + const { readmeTxtFile } = bundle.tasks.updateChangelog; + + return updateChangelog({ + changesetJsonFile: this.flags['changeset-json'], + readmeTxtFile: path.join(project.dir, readmeTxtFile), + packageName: project.packageJson.name, + version, + }); + }, + }, { title: 'Update requirements', task: async (_, task) => { diff --git a/tools/wpdev/src/utils/changelog.ts b/tools/wpdev/src/utils/changelog.ts index 3fdfe90f..6a0cee59 100644 --- a/tools/wpdev/src/utils/changelog.ts +++ b/tools/wpdev/src/utils/changelog.ts @@ -1,59 +1,84 @@ import fs from 'node:fs'; -import path from 'node:path'; -import { TaskTarget, globFiles } from './misc.js'; +import { z } from 'zod'; +import { UpdateChangelogOptions } from './schema.js'; -export type UpdateChangelogConfig = { - changelogPath: string; - readmeTxt: TaskTarget; -}; - -export async function updateChangelog( - cwd: string, - version: string, - config: UpdateChangelogConfig, -) { - const changelogPath = path.join(cwd, config.changelogPath); +export const ChangesetJsonSchema = z.object({ + changesets: z.array( + z.object({ + summary: z.string().optional().default(''), + id: z.string(), + }), + ), + releases: z.array( + z.object({ + name: z.string(), + type: z.string().optional(), + changesets: z.array(z.string()), + }), + ), +}); - if (!fs.existsSync(changelogPath)) { - throw new Error(`Changelog not found at "${changelogPath}"`); +export function readChangesetJson(changesetJsonFile: string) { + if (!changesetJsonFile || !fs.existsSync(changesetJsonFile)) { + throw new Error('Please provide a valid changeset JSON file.'); } + const json = JSON.parse(fs.readFileSync(changesetJsonFile, 'utf8')); - const changelogContents = fs.readFileSync(changelogPath, 'utf8'); - // Match anything between "## Unreleased" and the previous release tag like "## [0.0.0]" - const changelogRegex = /(?<=##\sUnreleased)[\s\S]+?(?=##\s?\[\d+\.\d+\.\d+)/i; - const changelogChanges = changelogContents.match(changelogRegex)?.[0].trim(); + return ChangesetJsonSchema.parse(json); +} - if (!changelogChanges) { - throw new Error('Cannot find changelog changes'); - } +type UpdateChangelogConfig = UpdateChangelogOptions & { + changesetJsonFile: string; + packageName: string; + version: string; +}; - // Match the one character after "== Changelog ==" to add the notes after it - const readmeTxtRegex = /== Changelog ==([\s\S])/i; +export function updateChangelog({ + changesetJsonFile, + readmeTxtFile, + packageName, + version, +}: UpdateChangelogConfig) { + const data = readChangesetJson(changesetJsonFile); - const readmeTxtChanges = '\n\n= {version} =\n{changes}\n'; + const changesetsMap = new Map( + data.changesets.map(({ id, summary }) => [id, summary]), + ); - const readmeTxtEntries = globFiles(config.readmeTxt, { cwd: cwd }); + const changes = []; - for (const file of readmeTxtEntries) { - const filePath = path.join(cwd, file); - const fileContents = fs.readFileSync(filePath, 'utf8'); + for (const { name, changesets } of data.releases) { + if (!changesets.length || name !== packageName) { + continue; + } + for (const changeset of changesets) { + const summary = changesetsMap.get(changeset); - const contents = fileContents.replace(readmeTxtRegex, (match, $1) => { - const changes = changelogChanges - // remove headings like Enhancements, Bug fixes - .replace(/(^|\n)(##.+)/g, '') - // replace empty lines - .replace(/\n[\s\t]*\n/g, '\n') - // cleanup - .trim(); + if (!summary) { + console.warn( + `Could not find changeset summary for changeset: "${changeset}"`, + ); + continue; + } - const replace = readmeTxtChanges - .replace('{version}', version) - .replace('{changes}', changes); + changes.push(`- ${summary}`); + } + } + + let readmeTxt = fs.readFileSync(readmeTxtFile, 'utf8'); - return match.replace($1, replace); - }); + const versionStr = `= ${version} =`; - fs.writeFileSync(filePath, contents); + if (!changes.length) { + changes.push('- Maintenance release.'); } + + const changesStr = changes.join('\n'); + + readmeTxt = readmeTxt.replace( + /== Changelog ==\n.*?\[See full changelog\]/s, + `== Changelog ==\n\n${versionStr}\n${changesStr}\n\n[See full changelog]`, + ); + + fs.writeFileSync(readmeTxtFile, readmeTxt); } diff --git a/tools/wpdev/src/utils/misc.ts b/tools/wpdev/src/utils/misc.ts index 942dcb29..725a0b31 100644 --- a/tools/wpdev/src/utils/misc.ts +++ b/tools/wpdev/src/utils/misc.ts @@ -29,6 +29,11 @@ export async function copyDir( { cwd: sourceDir }, ); + // Clean up destination directory + if (fs.existsSync(destDir)) { + fs.rmSync(destDir, { recursive: true }); + } + for (const file of entries) { const filePath = path.join(sourceDir, file); const destPath = path.join(destDir, file); diff --git a/tools/wpdev/src/utils/schema.ts b/tools/wpdev/src/utils/schema.ts index c6e3ab2a..bdac6598 100644 --- a/tools/wpdev/src/utils/schema.ts +++ b/tools/wpdev/src/utils/schema.ts @@ -106,6 +106,10 @@ const updateRequirementsData = z.object({ target: targetFilesSchema.describe('The target files.'), }); +const updateChangelogData = z.object({ + readmeTxtFile: z.string().optional().default('src/readme.txt'), +}); + const updateVersionData = z.array( z.discriminatedUnion('type', [ z @@ -150,6 +154,8 @@ const updateVersionData = z.array( ]), ); +export type UpdateChangelogOptions = z.infer; + export type UpdateVersionInput = z.input; export const bundleSchema = z @@ -160,6 +166,7 @@ export const bundleSchema = z copyFilesBefore: copyFilesData, updateRequirements: updateRequirementsData, updateVersion: updateVersionData, + updateChangelog: updateChangelogData, generatePot: generatePotData, updatePoFiles: updatePoFilesData, makeMoFiles: makeMoFilesData, diff --git a/tools/wpdev/src/utils/wp-monorepo.ts b/tools/wpdev/src/utils/wp-monorepo.ts index 0982c300..c1796d15 100644 --- a/tools/wpdev/src/utils/wp-monorepo.ts +++ b/tools/wpdev/src/utils/wp-monorepo.ts @@ -1,8 +1,7 @@ -import fs from 'node:fs'; import path from 'node:path'; import { getPackagesSync } from '@manypkg/get-packages'; import { execaSync } from 'execa'; -import { z } from 'zod'; +import { readChangesetJson } from './changelog.js'; import { ProjectType, UserConfig, WPProject, fixPackage } from './tools.js'; export type WPMonorepoConfig = { @@ -16,16 +15,6 @@ type IncludeOptions = { [key in ProjectStatus]?: boolean; }; -const ReleaseJsonSchema = z.object({ - releases: z.array( - z.object({ - name: z.string(), - type: z.string().optional(), - changesets: z.array(z.string()), - }), - ), -}); - export class WPMonorepo { config: WPMonorepoConfig; @@ -182,12 +171,7 @@ export class WPMonorepo { } getProjectsToRelease(changesetJsonFile: string) { - if (!fs.existsSync(changesetJsonFile)) { - throw new Error('Please provide a valid release JSON file.'); - } - const json = JSON.parse(fs.readFileSync(changesetJsonFile, 'utf8')); - - const projectNames = ReleaseJsonSchema.parse(json) + const projectNames = readChangesetJson(changesetJsonFile) // Get the names of projects that have changesets, ignoring the ones that don't .releases.filter(({ changesets }) => changesets.length) // Collect the names From 71b1cf888c4616645f6529b5fe96ac9cb275c83a Mon Sep 17 00:00:00 2001 From: Irshad Ahmad Date: Tue, 23 Jan 2024 10:38:16 +0530 Subject: [PATCH 10/12] Update deploy.yml --- .github/workflows/deploy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 6fb206c4..004883c8 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -7,8 +7,8 @@ on: concurrency: ${{ github.workflow }}-${{ github.ref }} jobs: - tag: - name: New release + deploy: + name: Deploy needs: [details] runs-on: ubuntu-latest if: ${{ fromJson(needs.details.outputs.result).shouldDeploy }} From c1e221702f7368d477a4c93fe684ed87278aabe5 Mon Sep 17 00:00:00 2001 From: Irshad Ahmad Date: Tue, 23 Jan 2024 11:12:57 +0530 Subject: [PATCH 11/12] Make copy files relative to source directory --- tools/wpdev/src/commands/bundle.ts | 38 +++++++++++++++++++++--------- tools/wpdev/src/utils/misc.ts | 26 +++++++------------- tools/wpdev/src/utils/schema.ts | 13 ++++++---- 3 files changed, 44 insertions(+), 33 deletions(-) diff --git a/tools/wpdev/src/commands/bundle.ts b/tools/wpdev/src/commands/bundle.ts index 8359c9d1..dbfcfb29 100644 --- a/tools/wpdev/src/commands/bundle.ts +++ b/tools/wpdev/src/commands/bundle.ts @@ -1,3 +1,4 @@ +import fs from 'node:fs'; import path from 'node:path'; import { Flags } from '@oclif/core'; import chalk from 'chalk'; @@ -10,7 +11,7 @@ import { potToPhp, updatePoFiles, } from '../utils/i18n.js'; -import { copyDir, getDistIgnorePattern, zipDir } from '../utils/misc.js'; +import { copyFiles, getDistIgnorePattern, zipDir } from '../utils/misc.js'; import { getNextVersion, getProjectConfig, @@ -168,6 +169,11 @@ export default class Bundle extends WithProjects { const outDir = this.getOutputDir(project); + // Clean up output directory + if (fs.existsSync(outDir)) { + fs.rmSync(outDir, { recursive: true }); + } + const canChangeSourceFiles = this.flags['update-source-files']; const cwd = canChangeSourceFiles ? project.dir : outDir; @@ -205,12 +211,17 @@ export default class Bundle extends WithProjects { return task.skip(); } - const { sourceDir, ignore = getDistIgnorePattern(project.dir) } = - bundle.tasks.copyFilesBefore; + const { + relativeSource, + files, + ignore = getDistIgnorePattern(project.dir), + } = bundle.tasks.copyFilesBefore; - return await copyDir(path.join(project.dir, sourceDir), outDir, { - ignore, - }); + return await copyFiles( + path.join(project.dir, relativeSource), + { files, ignore }, + outDir, + ); }, }, { @@ -356,12 +367,17 @@ export default class Bundle extends WithProjects { return task.skip(); } - const { sourceDir, ignore = getDistIgnorePattern(project.dir) } = - bundle.tasks.copyFilesAfter; + const { + relativeSource, + files, + ignore = getDistIgnorePattern(project.dir), + } = bundle.tasks.copyFilesAfter; - return await copyDir(path.join(project.dir, sourceDir), outDir, { - ignore, - }); + return await copyFiles( + path.join(project.dir, relativeSource), + { files, ignore }, + outDir, + ); }, }, { diff --git a/tools/wpdev/src/utils/misc.ts b/tools/wpdev/src/utils/misc.ts index 725a0b31..64ff650f 100644 --- a/tools/wpdev/src/utils/misc.ts +++ b/tools/wpdev/src/utils/misc.ts @@ -15,29 +15,21 @@ export function globFiles(target: TaskTarget, options?: Options) { }); } -export async function copyDir( - sourceDir: string, +export async function copyFiles( + cwd: string, + targetFiles: TaskTarget, destDir: string, - options?: Partial, ) { - const entries = globFiles( - { - files: ['**/*'], - ...options, - ignore: ['**/node_modules/**', ...(options?.ignore || [])], - }, - { cwd: sourceDir }, - ); - - // Clean up destination directory - if (fs.existsSync(destDir)) { - fs.rmSync(destDir, { recursive: true }); - } + const entries = globFiles(targetFiles, { cwd }); + + console.log(entries); for (const file of entries) { - const filePath = path.join(sourceDir, file); + const filePath = path.join(cwd, file); const destPath = path.join(destDir, file); + console.log({ file, filePath, destPath }); + if (!fs.existsSync(path.dirname(destPath))) { fs.mkdirSync(path.dirname(destPath), { recursive: true }); } diff --git a/tools/wpdev/src/utils/schema.ts b/tools/wpdev/src/utils/schema.ts index bdac6598..23a553e8 100644 --- a/tools/wpdev/src/utils/schema.ts +++ b/tools/wpdev/src/utils/schema.ts @@ -11,11 +11,14 @@ const targetFilesSchema = z.object({ }); const copyFilesData = z.object({ - sourceDir: z + relativeSource: z .string() .optional() .default('src') - .describe('The source directory.'), + .describe('The directory relative to which the source files are.'), + files: targetFilesSchema.shape.files + .optional() + .default(['**/*', '../CHANGELOG.md', '../README.md']), ignore: targetFilesSchema.shape.ignore, }); @@ -81,9 +84,9 @@ const processStylesData = z.object({ files: targetFilesSchema.shape.files .optional() .default(['src/assets/static/css/*.css']), - ignore: targetFilesSchema.shape.ignore - .optional() - .default(['src/assets/static/css/*.min.css']), + ignore: targetFilesSchema.shape.ignore.default([ + 'src/assets/static/css/*.min.css', + ]), }); const updatePoFilesData = z.object({ From 46b1f965d767fa0ab653109277ec9af9c5ac60b6 Mon Sep 17 00:00:00 2001 From: Irshad Ahmad Date: Tue, 23 Jan 2024 11:13:51 +0530 Subject: [PATCH 12/12] Update deploy.yml --- .github/workflows/deploy.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 004883c8..cf9f792f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -46,10 +46,6 @@ jobs: SVN_USERNAME: ${{ secrets.SVN_USERNAME || 'test' }} SVN_PASSWORD: ${{ secrets.SVN_PASSWORD || 'test' }} - - name: Copy README.md to dist - run: | - cp ${{ fromJson(needs.details.outputs.result).relativeDir }}/README.md dist/${{ fromJson(needs.details.outputs.result).relativeDir }}/README.md - - name: Deploy to repo uses: manzoorwanijk/action-deploy-to-repo@v3 with: