Remove all schema checking code from Code Analyzer. (#39487)

This commit is contained in:
Sam Seay 2023-08-01 09:47:10 +08:00 committed by GitHub
parent fb26613f03
commit 2ffdf6f968
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 47 additions and 455 deletions

View File

@ -3456,8 +3456,8 @@ importers:
specifier: ^1.10.0
version: 1.10.0
'@commander-js/extra-typings':
specifier: ^0.1.0
version: 0.1.0(commander@9.4.0)
specifier: ^10.0.3
version: 10.0.3(commander@9.4.0)
'@oclif/core':
specifier: ^2.4.0
version: 2.4.0
@ -4179,7 +4179,7 @@ packages:
'@babel/core': ^7.0.0-0
dependencies:
'@babel/core': 7.21.3
'@jridgewell/trace-mapping': 0.3.16
'@jridgewell/trace-mapping': 0.3.17
commander: 4.1.1
convert-source-map: 1.8.0
fs-readdir-recursive: 1.1.0
@ -10193,6 +10193,14 @@ packages:
commander: 10.0.1
dev: false
/@commander-js/extra-typings@10.0.3(commander@9.4.0):
resolution: {integrity: sha512-OIw28QV/GlP8k0B5CJTRsl8IyNvd0R8C8rfo54Yz9P388vCNDgdNrFlKxZTGqps+5j6lSw3Ss9JTQwcur1w1oA==}
peerDependencies:
commander: 10.0.x
dependencies:
commander: 9.4.0
dev: false
/@cspotcode/source-map-support@0.8.1:
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
@ -11734,6 +11742,7 @@ packages:
dependencies:
'@jridgewell/resolve-uri': 3.1.0
'@jridgewell/sourcemap-codec': 1.4.14
dev: true
/@jridgewell/trace-mapping@0.3.17:
resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==}
@ -16996,7 +17005,7 @@ packages:
functional-red-black-tree: 1.0.1
ignore: 5.2.0
regexpp: 3.2.0
semver: 7.5.0
semver: 7.5.3
tsutils: 3.21.0(typescript@4.9.5)
typescript: 4.9.5
transitivePeerDependencies:
@ -17210,7 +17219,7 @@ packages:
debug: 4.3.4(supports-color@9.2.2)
globby: 11.1.0
is-glob: 4.0.3
semver: 7.5.0
semver: 7.5.3
tsutils: 3.21.0(typescript@4.9.5)
typescript: 4.9.5
transitivePeerDependencies:
@ -26697,7 +26706,7 @@ packages:
jsdoctypeparser: 9.0.0
lodash: 4.17.21
regextras: 0.7.1
semver: 7.5.0
semver: 7.5.3
spdx-expression-parse: 3.0.1
transitivePeerDependencies:
- supports-color
@ -26717,7 +26726,7 @@ packages:
jsdoc-type-pratt-parser: 1.2.0
lodash: 4.17.21
regextras: 0.8.0
semver: 7.5.0
semver: 7.5.3
spdx-expression-parse: 3.0.1
transitivePeerDependencies:
- supports-color
@ -36164,7 +36173,7 @@ packages:
dependencies:
growly: 1.3.0
is-wsl: 2.2.0
semver: 7.5.0
semver: 7.5.3
shellwords: 0.1.1
uuid: 8.3.2
which: 2.0.2

View File

@ -1,6 +1,6 @@
{
"name": "code-analyzer",
"version": "0.0.1",
"version": "1.0.0",
"description": "A tool to analyze code changes in WooCommerce Monorepo.",
"author": "Automattic",
"homepage": "https://github.com/woocommerce/woocommerce",
@ -8,7 +8,7 @@
"repository": "woocommerce/woocommerce",
"dependencies": {
"@actions/core": "^1.10.0",
"@commander-js/extra-typings": "^0.1.0",
"@commander-js/extra-typings": "^10.0.3",
"@woocommerce/monorepo-utils": "workspace:*",
"@oclif/core": "^2.4.0",
"@tsconfig/node16": "^1.0.3",

View File

@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { Command } from '@commander-js/extra-typings';
import { Command, Option } from '@commander-js/extra-typings';
import { Logger } from '@woocommerce/monorepo-utils/src/core/logger';
import { join } from 'path';
@ -12,7 +12,6 @@ import { scanForChanges } from '../../lib/scan-changes';
import {
printDatabaseUpdates,
printHookResults,
printSchemaChange,
printTemplateResults,
} from '../../print';
@ -36,22 +35,18 @@ const program = new Command()
'Git repo url or local path to a git repo.',
join( process.cwd(), '../../' )
)
.option(
'-o, --outputStyle <outputStyle>',
'Output style for the results. Options: github, cli. Github output will set the results as an output variable for Github actions.',
'cli'
)
.option(
'-ss, --skipSchemaCheck',
'Skip the schema check, enable this if you are not analyzing WooCommerce'
.addOption(
new Option( '-o, --outputStyle <outputStyle>' ).choices( [
'github',
'cli',
] as const )
)
.action( async ( compare, sinceVersion, options ) => {
const { skipSchemaCheck = false, source, base, outputStyle } = options;
const { source, base, outputStyle = 'cli' } = options;
const changes = await scanForChanges(
compare,
sinceVersion,
skipSchemaCheck,
source,
base,
outputStyle
@ -93,24 +88,6 @@ const program = new Command()
);
}
if ( changes.schema.filter( ( s ) => ! s.areEqual ).length ) {
printSchemaChange(
changes.schema,
sinceVersion,
outputStyle,
Logger.notice
);
} else {
Logger.notice( '\n\n## SCHEMA CHANGES' );
Logger.notice(
'---------------------------------------------------'
);
Logger.notice( 'No schema changes found.' );
Logger.notice(
'---------------------------------------------------'
);
}
if ( changes.db ) {
printDatabaseUpdates( changes.db, outputStyle, Logger.notice );
} else {

View File

@ -11,14 +11,12 @@ import { join } from 'path';
import {
scanChangesForDB,
scanChangesForHooks,
scanChangesForSchema,
scanChangesForTemplates,
ScanType,
} from '../../lib/scan-changes';
import {
printDatabaseUpdates,
printHookResults,
printSchemaChange,
printTemplateResults,
} from '../../print';
@ -33,7 +31,7 @@ const program = new Command()
.command( 'scan' )
.argument(
'<type>',
'Type of change to scan for. Options: templates, hooks, database, schema.'
'Type of change to scan for. Options: templates, hooks, database.'
)
.argument(
'<compare>',
@ -46,7 +44,7 @@ const program = new Command()
)
.option(
'-s, --since <sinceVersion>',
'Specify the version used to determine which changes are included (version listed in @since code doc). Only needed for hook, template, schema changes.'
'Specify the version used to determine which changes are included (version listed in @since code doc). Only needed for hook and template changes.'
)
.option(
'-src, --source <source>',
@ -62,12 +60,10 @@ const program = new Command()
const { since: sinceVersion, source, outputStyle } = options;
if (
( scanType === 'hooks' ||
scanType === 'templates' ||
scanType === 'schema' ) &&
( scanType === 'hooks' || scanType === 'templates' ) &&
! sinceVersion
) {
throw new Error(
Logger.error(
`To scan for ${ scanType } changes you must provide the since argument.`
);
}
@ -128,26 +124,9 @@ const program = new Command()
printEmptyNotice( 'database' );
}
break;
case 'schema':
const schemaChanges = await scanChangesForSchema(
compare,
base,
source
);
if ( schemaChanges && schemaChanges.length && sinceVersion ) {
printSchemaChange(
schemaChanges,
sinceVersion,
'cli',
Logger.notice
);
} else {
printEmptyNotice( 'schema' );
}
break;
default:
throw new Error(
'Invalid scan type. Options: templates, hooks, database, schema.'
Logger.error(
`Invalid scan type: ${ scanType } Options: templates, hooks, database.`
);
}
} );

View File

@ -1,146 +0,0 @@
/**
* External dependencies
*/
import { join } from 'path';
import { simpleGit } from 'simple-git';
import { execAsync } from '@woocommerce/monorepo-utils/src/core/util';
import {
startWPEnv,
stopWPEnv,
} from '@woocommerce/monorepo-utils/src/core/wpenv';
export type SchemaDump = {
schema: string;
OrdersTableDataStore: string;
};
/**
* Get all schema strings found in WooCommerce.
*
* @param {string} tmpRepoPath - filepath to the repo to generate a schema from.
* @param {Function} error - Error logging function.
* @return {Object} Object of schema strings.
*/
export const getSchema = async (
tmpRepoPath: string,
error: ( s: string ) => void
): Promise< SchemaDump | void > => {
try {
const pluginPath = join( tmpRepoPath, 'plugins/woocommerce' );
const getSchemaPath =
'wp-content/plugins/woocommerce/bin/wc-get-schema.php';
// Get the WooCommerce schema from wp cli
const schemaOutput = await execAsync(
`wp-env run cli wp eval-file '${ getSchemaPath }'`,
{
cwd: pluginPath,
encoding: 'utf-8',
}
);
// Get the OrdersTableDataStore schema.
const ordersTableOutput = await execAsync(
'wp-env run cli wp eval \'echo (new Automattic\\WooCommerce\\Internal\\DataStores\\Orders\\OrdersTableDataStore)->get_database_schema();\'',
{
cwd: pluginPath,
encoding: 'utf-8',
}
);
return {
schema: schemaOutput.stdout,
OrdersTableDataStore: ordersTableOutput.stdout,
};
} catch ( e ) {
if ( e instanceof Error ) {
error( e.message );
}
}
};
export type SchemaDiff = {
name: string;
description: string;
base: string;
compare: string;
method: string;
areEqual: boolean;
};
/**
* Generate a schema for each branch being compared.
*
* @param {string} tmpRepoPath Path to repository used to generate schema diff.
* @param {string} compare Branch/commit hash to compare against the base.
* @param {string} base Base branch/commit hash.
* @param {Function} build Build to perform between checkouts.
* @param {Function} error error print method.
* @return {Promise<SchemaDiff[]|null>} diff object.
*/
export const generateSchemaDiff = async (
tmpRepoPath: string,
compare: string,
base: string,
build: () => Promise< void > | void,
error: ( s: string ) => void
): Promise< SchemaDiff[] | null > => {
const git = simpleGit( {
baseDir: tmpRepoPath,
config: [ 'core.hooksPath=/dev/null' ],
} );
// Be sure the wp-env engine is started.
await startWPEnv( tmpRepoPath, error );
// Force checkout because sometimes a build will generate a lockfile change.
await git.checkout( base, [ '--force' ] );
await build();
const baseSchema = await getSchema(
tmpRepoPath,
( errorMessage: string ) => {
error(
`Unable to get schema for branch ${ base }. \n${ errorMessage }`
);
}
);
// Force checkout because sometimes a build will generate a lockfile change.
await git.checkout( compare, [ '--force' ] );
await build();
const compareSchema = await getSchema(
tmpRepoPath,
( errorMessage: string ) => {
error(
`Unable to get schema for branch ${ compare }. \n${ errorMessage }`
);
}
);
await stopWPEnv( tmpRepoPath, error );
if ( ! baseSchema || ! compareSchema ) {
return null;
}
return [
{
name: 'schema',
description: 'WooCommerce Base Schema',
base: baseSchema.schema,
compare: compareSchema.schema,
method: 'WC_Install->get_schema',
areEqual: baseSchema.schema === compareSchema.schema,
},
{
name: 'OrdersTableDataStore',
description: 'OrdersTableDataStore Schema',
base: baseSchema.OrdersTableDataStore,
compare: compareSchema.OrdersTableDataStore,
method: 'Automattic\\WooCommerce\\Internal\\DataStores\\Orders\\OrdersTableDataStore->get_database_schema',
areEqual:
baseSchema.OrdersTableDataStore ===
compareSchema.OrdersTableDataStore,
},
];
};

View File

@ -2,25 +2,20 @@
* External dependencies
*/
import { Logger } from '@woocommerce/monorepo-utils/src/core/logger';
import { join } from 'path';
import {
cloneRepo,
generateDiff,
} from '@woocommerce/monorepo-utils/src/core/git';
import { readFile } from 'fs/promises';
import { execSync } from 'child_process';
/**
* Internal dependencies
*/
import { execAsync } from '../utils';
import { scanForDBChanges } from './db-changes';
import { scanForHookChanges } from './hook-changes';
import { scanForTemplateChanges } from './template-changes';
import { SchemaDiff, generateSchemaDiff } from '../git';
import { scanForSchemaChanges } from './schema-changes';
export type ScanType = 'schema' | 'db' | 'hooks' | 'templates' | string;
export type ScanType = 'db' | 'hooks' | 'templates' | string;
const generateVersionDiff = async (
compareVersion: string,
@ -118,29 +113,12 @@ export const scanChangesForTemplates = async (
return Array.from( templateChanges.values() );
};
export const scanChangesForSchema = async (
compareVersion: string,
base: string,
source: string,
clonedPath?: string
) => {
const { tmpRepoPath } = await generateVersionDiff(
compareVersion,
base,
source,
clonedPath
);
return scanForSchemaChanges( compareVersion, base, tmpRepoPath );
};
export const scanForChanges = async (
compareVersion: string,
sinceVersion: string,
skipSchemaCheck: boolean,
source: string,
base: string,
outputStyle: string,
outputStyle: 'cli' | 'github',
clonedPath?: string
) => {
Logger.startTask( `Making temporary clone of ${ source }...` );
@ -178,8 +156,6 @@ export const scanForChanges = async (
);
}
const pluginPath = join( tmpRepoPath, 'plugins/woocommerce' );
Logger.startTask( 'Detecting hook changes...' );
const hookChanges = await scanForHookChanges(
diff,
@ -200,60 +176,9 @@ export const scanForChanges = async (
const dbChanges = scanForDBChanges( diff );
Logger.endTask();
let schemaChanges: SchemaDiff[] = [];
if ( ! skipSchemaCheck ) {
const build = async () => {
const fileStr = await readFile(
join( pluginPath, 'package.json' ),
'utf-8'
);
const packageJSON = JSON.parse( fileStr );
// Temporarily save the current PNPM version.
await execAsync( `tmpgPNPM="$(pnpm --version)"` );
if ( packageJSON.engines && packageJSON.engines.pnpm ) {
await execAsync(
`npm i -g pnpm@${ packageJSON.engines.pnpm }`,
{
cwd: pluginPath,
}
);
}
// Note doing the minimal work to get a DB scan to work, avoiding full build for speed.
await execAsync( 'composer install', { cwd: pluginPath } );
await execAsync(
'pnpm run --filter=woocommerce build:feature-config',
{
cwd: pluginPath,
}
);
};
Logger.startTask( 'Generating schema diff...' );
const schemaDiff = await generateSchemaDiff(
tmpRepoPath,
compareVersion,
base,
build,
Logger.error
);
schemaChanges = schemaDiff || [];
// Restore the previously saved PNPM version
await execAsync( `npm i -g pnpm@"$tmpgPNPM"` );
Logger.endTask();
}
return {
hooks: hookChanges,
templates: templateChanges,
schema: schemaChanges,
db: dbChanges,
};
};

View File

@ -1,60 +0,0 @@
/**
* External dependencies
*/
import { Logger } from '@woocommerce/monorepo-utils/src/core/logger';
import { readFile } from 'fs/promises';
import { join } from 'path';
/**
* Internal dependencies
*/
import { generateSchemaDiff } from '../git';
import { execAsync } from '../utils';
export const scanForSchemaChanges = async (
compareVersion: string,
base: string,
tmpRepoPath: string
) => {
const pluginPath = join( tmpRepoPath, 'plugins/woocommerce' );
const build = async () => {
const fileStr = await readFile(
join( pluginPath, 'package.json' ),
'utf-8'
);
const packageJSON = JSON.parse( fileStr );
// Temporarily save the current PNPM version.
await execAsync( `tmpgPNPM="$(pnpm --version)"` );
if ( packageJSON.engines && packageJSON.engines.pnpm ) {
await execAsync( `npm i -g pnpm@${ packageJSON.engines.pnpm }`, {
cwd: pluginPath,
} );
}
// Note doing the minimal work to get a DB scan to work, avoiding full build for speed.
await execAsync( 'composer install', { cwd: pluginPath } );
await execAsync( 'pnpm run --filter=woocommerce build:feature-config', {
cwd: pluginPath,
} );
};
Logger.startTask( 'Generating schema diff...' );
const schemaDiff = await generateSchemaDiff(
tmpRepoPath,
compareVersion,
base,
build,
Logger.error
);
// Restore the previously saved PNPM version
await execAsync( `npm i -g pnpm@"$tmpgPNPM"` );
Logger.endTask();
return schemaDiff;
};

View File

@ -6,7 +6,6 @@ import { setOutput } from '@actions/core';
/**
* Internal dependencies
*/
import { SchemaDiff } from './git';
import { HookChangeDescription } from './lib/hook-changes';
import { TemplateChangeDescription } from './lib/template-changes';
@ -113,43 +112,6 @@ export const printHookResults = (
}
};
/**
* Print Schema change results.
*
* @param {Object} schemaDiffs Schema diff object
* @param {string} version Version change was introduced.
* @param {string} output Output style.
* @param {Function} log Print method.
*/
export const printSchemaChange = (
schemaDiffs: SchemaDiff[],
version: string,
output: string,
log: ( s: string ) => void
) => {
if ( output === 'github' ) {
let githubCommentContent = '\\n\\n### New schema changes:';
schemaDiffs.forEach( ( schemaDiff ) => {
if ( ! schemaDiff.areEqual ) {
githubCommentContent += `\\n* **Schema:** ${ schemaDiff.method } introduced in ${ version }`;
}
} );
setOutput( 'schema', githubCommentContent );
} else {
log( '\n## SCHEMA CHANGES' );
log( '---------------------------------------------------' );
schemaDiffs.forEach( ( schemaDiff ) => {
if ( ! schemaDiff.areEqual ) {
log(
` NOTICE | Schema changes detected in ${ schemaDiff.method } as of ${ version }`
);
log( '---------------------------------------------------' );
}
} );
}
};
/**
*
* @param {Object} databaseUpdates Database update info.

View File

@ -4,11 +4,6 @@
import { exec } from 'child_process';
import { promisify } from 'util';
/**
* Internal dependencies
*/
import { SchemaDiff } from './git';
export const execAsync = promisify( exec );
/**
@ -41,16 +36,6 @@ export const getHookName = ( name: string ): string => {
return name.replace( /(\'|\")/g, '' ).trim();
};
/**
* Determine if schema diff object contains schemas that are equal.
*
* @param {Array<SchemaDiff>} schemaDiffs
* @return {boolean|void} If the schema diff describes schemas that are equal.
*/
export const areSchemasEqual = ( schemaDiffs: SchemaDiff[] ): boolean => {
return ! schemaDiffs.some( ( s ) => ! s.areEqual );
};
/**
* Extract hook description from a raw diff.
*

View File

@ -10,10 +10,11 @@ don't have access to a WordPress.com auth token.
1. Make sure `pnpm i` has been run in the monorepo.
2. Make sure you have added a `.env` file with the env variables set. WCCOM_TOKEN is optional if you're using `--outputOnly`, but
the `GITHUB_ACCESS_TOKEN` is required. If you need help generating a token see [the docs](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token). To silence all CLI output, set `LOGGER_LEVEL` to `"silent"`.
the `GITHUB_ACCESS_TOKEN` is required. If you need help generating a token see [the docs](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token). To silence all CLI output, set `LOGGER_LEVEL` to `"silent"`.
3. Note that the env file should live at the same path that you're running the command from.
4. Run the tool via the npm script, e.g. `pnpm run release-post -- "6.8.0" --outputOnly`
5. For more help on individual options, run the help `pnpm run release-post -- --help`
4. Run the tool via the npm script, e.g. `pnpm run release-post release "6.8.0" --outputOnly`
5. For more help on individual options, run the help `pnpm run release-post <command> --help`. e.g. `pnpm run release-post rc --help`
### Publishing Draft Posts
This tool will publish draft posts to `https://developer.woocommerce.com` for you if you omit the `--outputOnly` flag. There is some minimal first time setup for this though:
@ -21,25 +22,24 @@ This tool will publish draft posts to `https://developer.woocommerce.com` for yo
1. Create an app on WordPress.com [here](https://developer.wordpress.com/apps/).
2. Recommended settings:
* Name can be anything
* Description can be left blank
* Website URL just put http://localhost
* Redirect URLs, by default you should add: http://localhost:3000/oauth
* JavaScript Origins put http://localhost
* Type - choose "Web"
- Name can be anything
- Description can be left blank
- Website URL just put http://localhost
- Redirect URLs, by default you should add: http://localhost:3000/oauth
- JavaScript Origins put http://localhost
- Type - choose "Web"
3. Once your app is created you can go back to the
app list and click "manage app".
app list and click "manage app".
4. Take note of the `client secret` and the `client id`.
5. In your `.env` file add the client secret to the `WPCOM_OAUTH_CLIENT_SECRET` variable and the client id to the `WPCOM_OAUTH_CLIENT_ID` variable.
### Generating Just a Contributors List
If you don't have a final release yet you can generate an HTML contributors list that you can copy
paste into a blank post.
To do that simply run `pnpm run release-post contributors -- "<currentVersion>" "<previousVersion>"`
To do that simply run `pnpm run release-post contributors "<currentVersion>" "<previousVersion>"`
### Advanced
@ -49,9 +49,3 @@ Steps:
1. Add your preferred redirect URI to the `WPCOM_OAUTH_REDIRECT_URI` variable in `.env`. e.g. `http://localhost:4321/oauth`
2. When creating your app on [WordPress.com](https://developer.wordpress.com/apps/) make sure the redirect URL you set matches the one set in `.env`

View File

@ -171,15 +171,12 @@ const program = new Command()
const changes = await scanForChanges(
currentVersionRef,
`${ previousParsed.major }.${ previousParsed.minor }.${ previousParsed.patch }`,
false,
SOURCE_REPO,
previousVersionRef,
'cli',
tmpRepoPath
);
const schemaChanges = changes.schema.filter( ( s ) => ! s.areEqual );
Logger.startTask( 'Finding contributors' );
const title = `WooCommerce ${ currentVersion } Released`;
@ -191,10 +188,7 @@ const program = new Command()
const postVariables = {
contributors,
title,
changes: {
...changes,
schema: schemaChanges,
},
changes,
displayVersion: currentVersion,
};

View File

@ -2,33 +2,6 @@
<h2 id="database-changes">Database Changes</h2>
<!-- /wp:heading -->
<% if (changes.schema.length) { %>
<!-- wp:heading -->
<h3 id="schema-updates">Schema Updates</h3>
<!-- /wp:heading -->
<!-- wp:table -->
<figure class="wp-block-table">
<table>
<tbody>
<tr>
<th><strong>Class Name</strong></th>
<th><strong>Code Ref</strong></th>
</tr>
<% changes.schema.forEach(({areEqual, name, method}) => { %>
<% if (!areEqual) { %>
<tr>
<td><%= name %></td>
<td><code><%= method %></code></td>
</tr>
<% } %>
<% }) %>
</tbody>
</table>
</figure>
<!-- /wp:table -->
<% } %>
<% if (changes.db) { %>
<!-- wp:heading -->
<h3 id="db-updates">DB Updates</h3>