Skip to content

Commit 2473895

Browse files
committed
Release Pressship 0.1.9
1 parent 0ddced4 commit 2473895

11 files changed

Lines changed: 191 additions & 6 deletions

File tree

README.md

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ npx pressship login
5252
# 2. (Optional) Verify the saved session
5353
npx pressship whoami
5454

55-
# 3. Validate, package, and check without uploading
56-
npx pressship publish ./my-plugin --dry-run
55+
# 3. Verify the plugin without packaging or uploading
56+
npx pressship verify ./my-plugin
5757

5858
# 4. Submit for review or release an approved plugin
5959
npx pressship publish ./my-plugin
@@ -96,6 +96,7 @@ Playwright Chromium is installed automatically the first time browser automation
9696
| `pressship get` | Checkout or update a WordPress.org plugin SVN working copy. |
9797
| `pressship status` | Read review state from the logged-in developer dashboard. |
9898
| `pressship version <patch\|minor\|major>` | Bump the plugin header version and readme stable tag together. |
99+
| `pressship verify` | Run readme validation and Plugin Check without creating a zip. |
99100
| `pressship pack` | Validate, run Plugin Check, and write an installable zip. |
100101
| `pressship publish` | Route to submit or release based on current state. |
101102
| `pressship submit` | Upload a zip to WordPress.org review (or reupload). |
@@ -149,6 +150,19 @@ Need fine-grained control? Use the explicit subcommands `submit` and `release`.
149150

150151
## Packaging
151152

153+
```bash
154+
pressship verify ./my-plugin
155+
```
156+
157+
Runs readme validation and Plugin Check without writing a zip or publishing anything.
158+
159+
```bash
160+
pressship verify ./my-plugin --ignore "assets/**/*.mp4"
161+
pressship verify ./my-plugin --skip-readme-validator
162+
pressship verify ./my-plugin --wp-path /path/to/wordpress
163+
pressship verify ./my-plugin --json
164+
```
165+
152166
```bash
153167
pressship pack ./my-plugin
154168
```

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "pressship",
3-
"version": "0.1.8",
3+
"version": "0.1.9",
44
"description": "Submit and release WordPress.org plugins from the command line.",
55
"homepage": "https://pressship.org",
66
"bin": {

src/cli.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { login } from "./auth/login.js";
44
import { logout } from "./auth/logout.js";
55
import { whoami, type WhoamiOptions } from "./auth/whoami.js";
66
import { pack, type PackOptions } from "./package/pack.js";
7+
import { verify, type VerifyOptions } from "./package/verify.js";
78
import { publish, type PublishOptions } from "./wordpress-org/publish.js";
89
import { submit, type SubmitOptions } from "./wordpress-org/submit.js";
910
import { status, type StatusOptions } from "./wordpress-org/state.js";
@@ -98,6 +99,16 @@ program
9899
.option("-y, --yes", "Continue without interactive confirmations where possible")
99100
.action((pluginPath: string | undefined, options: PublishOptions) => run(() => publish(pluginPath, options))());
100101

102+
program
103+
.command("verify")
104+
.description("Run readme validation and Plugin Check without packaging or publishing.")
105+
.argument("[plugin-path]", "Path to the WordPress plugin directory")
106+
.option("--ignore <glob>", "Ignore files while staging Plugin Check; repeat for multiple globs", collectValues, [])
107+
.option("--skip-readme-validator", "Skip the remote WordPress.org readme validator")
108+
.option("--wp-path <path>", "WordPress installation path for `wp plugin check`")
109+
.option("--json", "Print verification details as JSON")
110+
.action((pluginPath: string | undefined, options: VerifyOptions) => run(() => verify(pluginPath, options))());
111+
101112
program
102113
.command("pack")
103114
.description("Create a WordPress-installable plugin zip, similar to npm pack.")

src/package/verify.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import path from "node:path";
2+
import { z } from "zod";
3+
import { hasBlockingFindings, printFindings } from "../checks/summary.js";
4+
import { discoverPluginProject } from "../plugin/discover.js";
5+
import type { PluginProject } from "../types.js";
6+
import { ui } from "../ui.js";
7+
import { validatePluginPack, type PackValidationResult } from "./pack.js";
8+
9+
const verifyOptionsSchema = z.object({
10+
ignore: z.array(z.string()).default([]),
11+
skipReadmeValidator: z.boolean().default(false),
12+
wpPath: z.string().optional(),
13+
json: z.boolean().default(false)
14+
});
15+
16+
export type VerifyOptions = z.input<typeof verifyOptionsSchema>;
17+
18+
export type VerifySummary = {
19+
ok: boolean;
20+
plugin: {
21+
rootDir: string;
22+
mainFile: string;
23+
name: string;
24+
slug: string;
25+
version?: string;
26+
readmePath?: string;
27+
};
28+
validation: PackValidationResult;
29+
};
30+
31+
export async function verify(pluginPath: string | undefined, rawOptions: VerifyOptions): Promise<void> {
32+
const options = verifyOptionsSchema.parse(rawOptions);
33+
34+
if (!options.json) {
35+
ui.intro("Verify WordPress plugin");
36+
}
37+
38+
const rootDir = path.resolve(pluginPath ?? process.cwd());
39+
const project = options.json
40+
? await discoverPluginProject(rootDir)
41+
: await ui.task("Discovering WordPress plugin", () => discoverPluginProject(rootDir), (value) =>
42+
`Discovered ${value.headers.pluginName}`
43+
);
44+
const validation = options.json
45+
? await validatePluginPack(project, options)
46+
: await ui.task("Verifying plugin", () => validatePluginPack(project, options));
47+
const summary = summarizeVerifyResult(project, validation);
48+
49+
if (options.json) {
50+
console.log(JSON.stringify(summary, null, 2));
51+
if (!summary.ok) {
52+
process.exitCode = 1;
53+
}
54+
return;
55+
}
56+
57+
printFindings("Readme validation", validation.readmeFindings);
58+
printFindings("Plugin Check", validation.pluginCheckFindings);
59+
60+
if (!summary.ok) {
61+
throw new Error("Verification reported blocking findings.");
62+
}
63+
64+
ui.success("Verification passed.");
65+
}
66+
67+
export function summarizeVerifyResult(
68+
project: PluginProject,
69+
validation: PackValidationResult
70+
): VerifySummary {
71+
return {
72+
ok: !hasBlockingFindings(validation.readmeFindings) && !hasBlockingFindings(validation.pluginCheckFindings),
73+
plugin: {
74+
rootDir: project.rootDir,
75+
mainFile: project.mainFile,
76+
name: project.headers.pluginName,
77+
slug: project.slug,
78+
version: project.version,
79+
readmePath: project.readmePath
80+
},
81+
validation
82+
};
83+
}

tests/plugin.test.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import path from "node:path";
44
import { describe, expect, it } from "vitest";
55
import { createPluginZip, listPackageFiles, stagePluginDirectory } from "../src/package/archive.js";
66
import { createPluginPack, skippedPackValidation, summarizePackResult, validatePluginPack } from "../src/package/pack.js";
7+
import { summarizeVerifyResult } from "../src/package/verify.js";
78
import { discoverPluginProject, resolvePluginProjectPath } from "../src/plugin/discover.js";
89
import { parsePluginHeaders } from "../src/plugin/headers.js";
910
import { parseReadme, validateReadmeLocally } from "../src/plugin/readme.js";
@@ -216,6 +217,49 @@ describe("packaging", () => {
216217
});
217218
});
218219

220+
describe("verification", () => {
221+
it("summarizes successful verification results", async () => {
222+
const root = await samplePlugin();
223+
const project = await discoverPluginProject(root);
224+
225+
expect(summarizeVerifyResult(project, skippedPackValidation())).toMatchObject({
226+
ok: true,
227+
plugin: {
228+
rootDir: root,
229+
mainFile: path.join(root, "example-plugin.php"),
230+
name: "Example Plugin",
231+
slug: "example-plugin",
232+
version: "1.2.3",
233+
readmePath: path.join(root, "readme.txt")
234+
},
235+
validation: {
236+
skipped: true,
237+
readmeFindings: [],
238+
pluginCheckFindings: []
239+
}
240+
});
241+
});
242+
243+
it("marks blocking verification findings as not ok", async () => {
244+
const root = await samplePlugin();
245+
const project = await discoverPluginProject(root);
246+
247+
expect(
248+
summarizeVerifyResult(project, {
249+
skipped: false,
250+
readmeFindings: [
251+
{
252+
severity: "error",
253+
code: "readme.invalid",
254+
message: "Readme is invalid."
255+
}
256+
],
257+
pluginCheckFindings: []
258+
}).ok
259+
).toBe(false);
260+
});
261+
});
262+
219263
describe("version bumps", () => {
220264
it("bumps semver patch, minor, and major", () => {
221265
expect(bumpVersion("1.2.3", "patch")).toBe("1.2.4");

website/docs/commands/verify.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
---
2+
sidebar_position: 6
3+
---
4+
5+
# Verify
6+
7+
```bash
8+
npx pressship verify ./my-plugin
9+
```
10+
11+
`verify` runs Pressship's publishing checks without creating a zip, uploading a submission, or touching SVN.
12+
13+
It checks:
14+
15+
- local `readme.txt` metadata;
16+
- the remote WordPress.org readme validator;
17+
- the official WordPress.org Plugin Check.
18+
19+
The command exits with a non-zero status when blocking findings are reported.
20+
21+
## Options
22+
23+
```bash
24+
pressship verify ./my-plugin --ignore "assets/**/*.mp4"
25+
pressship verify ./my-plugin --skip-readme-validator
26+
pressship verify ./my-plugin --wp-path /path/to/wordpress
27+
pressship verify ./my-plugin --json
28+
```

website/docs/getting-started.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,11 @@ npx pressship status ./my-plugin
3333
## Package And Validate
3434

3535
```bash
36+
npx pressship verify ./my-plugin
3637
npx pressship pack ./my-plugin
3738
```
3839

39-
`pack` validates `readme.txt`, runs Plugin Check, and writes a WordPress-installable `{slug}.zip` to the current directory.
40+
`verify` validates `readme.txt` and runs Plugin Check without creating an artifact. `pack` runs the same checks and writes a WordPress-installable `{slug}.zip` to the current directory.
4041

4142
## Publish
4243

website/docs/guides/plugin-check.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ It can automatically:
2020
This means most users can run:
2121

2222
```bash
23+
pressship verify ./my-plugin
2324
pressship submit ./my-plugin --dry-run
2425
```
2526

@@ -29,6 +30,7 @@ If you already have a local WordPress install with Plugin Check available, pass
2930

3031
```bash
3132
pressship submit ./my-plugin --wp-path /path/to/wordpress
33+
pressship verify ./my-plugin --wp-path /path/to/wordpress
3234
pressship pack ./my-plugin --wp-path /path/to/wordpress
3335
pressship release ./my-plugin --wp-path /path/to/wordpress
3436
```

website/docs/intro.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ npx pressship publish ./my-plugin
2020
- Plugin discovery from WordPress plugin headers.
2121
- `readme.txt` parsing and WordPress.org readme validation.
2222
- Managed WordPress.org Plugin Check setup.
23+
- Standalone `verify` checks before packaging or publishing.
2324
- WordPress-installable zip generation.
2425
- Smart `publish` routing between review submission and SVN release.
2526
- Explicit `submit` and `release` commands for WordPress.org workflows.

0 commit comments

Comments
 (0)