@wpelevator/wp-release 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -4
- package/dist/commands/deploy-svn.d.ts +3 -0
- package/dist/commands/deploy-svn.js +5 -0
- package/dist/deploy-options.d.ts +4 -1
- package/dist/deploy-options.js +5 -4
- package/dist/svn-deploy.d.ts +3 -2
- package/dist/svn-deploy.js +41 -25
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -153,6 +153,7 @@ wp-release version-check --constant MY_PLUGIN_VERSION --git-tag v1.2.0
|
|
|
153
153
|
| Flag | Default | Writes |
|
|
154
154
|
|---|---|---|
|
|
155
155
|
| `--trunk` | off | Sync the full source directory to `trunk/` |
|
|
156
|
+
| `--readme-only` | off | Sync only the readme to `trunk/`, for updates between releases such as bumping `Tested up to`. Can't be combined with `--svn-tag`. |
|
|
156
157
|
| `--svn-tag <version>` | off | Copy `trunk/` to `tags/<version>`. Without `--trunk`, the tag is copied from the repository's current `trunk/`. A leading `v` is stripped, so `v1.2.0` creates `tags/1.2.0`. |
|
|
157
158
|
| `--assets-dir <dir>` | not set | Sync this directory with banners, icons and screenshots to the SVN `assets/` directory. There's no default directory, so assets are only deployed when this is set, and it must exist. |
|
|
158
159
|
| `--no-assets` | | Skip the `--assets-dir` sync for one run, for example when a config always passes `--assets-dir`. |
|
|
@@ -163,6 +164,9 @@ Typical runs:
|
|
|
163
164
|
# Deploy 1.2.0 to trunk and the tag, and update the assets
|
|
164
165
|
wp-release deploy-svn dist --trunk --svn-tag 1.2.0 --assets-dir .wordpress-org
|
|
165
166
|
|
|
167
|
+
# Update only the readme between releases
|
|
168
|
+
wp-release deploy-svn dist --readme-only
|
|
169
|
+
|
|
166
170
|
# Update only the assets
|
|
167
171
|
wp-release deploy-svn --assets-dir .wordpress-org
|
|
168
172
|
|
|
@@ -173,7 +177,7 @@ wp-release deploy-svn --from-zip my-plugin.1.2.0.zip --trunk --svn-tag 1.2.0
|
|
|
173
177
|
How a deploy works:
|
|
174
178
|
|
|
175
179
|
1. The options are validated, including the slug, version and readme name, before they're used in URLs or paths.
|
|
176
|
-
2. With `--trunk`, the files must be a plugin whose `Version` header matches the version, and with `--svn-tag` the readme `Stable tag` must match too. A tag-only run doesn't check the files, since it tags whatever is in `trunk/`. Nothing is checked out when a check fails.
|
|
180
|
+
2. With `--trunk`, the files must be a plugin whose `Version` header matches the version, and with `--svn-tag` the readme `Stable tag` must match too. A tag-only run doesn't check the files, since it tags whatever is in `trunk/`. `--readme-only` needs the readme. Nothing is checked out when a check fails.
|
|
177
181
|
3. The repository is checked out sparsely into a new temporary directory, with only the directories that the flags write to. A missing `assets/` (or `trunk/`, `tags/`) directory is created. The deploy stops when `tags/<version>` exists, unless `--force` replaces it.
|
|
178
182
|
4. The files are synced in Node.js, without `rsync`: new and changed files are copied, files that are no longer selected are deleted, and `svn add` and `svn delete` stage them, including files that svn ignores by default. `trunk/` is then copied to the tag with `svn copy`, from the working copy when trunk was written and from the repository otherwise.
|
|
179
183
|
5. Asset images get `svn:mime-type` set for PNG, JPEG, GIF and SVG, the formats that WordPress.org documents for plugin assets. Other formats keep the type that svn assigns.
|
|
@@ -185,8 +189,9 @@ Credentials are only needed for the commit, not for dry runs, no-op runs or `fil
|
|
|
185
189
|
|
|
186
190
|
Validation:
|
|
187
191
|
|
|
188
|
-
-
|
|
192
|
+
- `--readme-only` can't be combined with `--svn-tag`, since a tag is a release snapshot that a readme update never changes.
|
|
189
193
|
- `--version` defaults to `--svn-tag`, then the `Version` header of the deployed files; when `--version` and `--svn-tag` are both set they must match.
|
|
194
|
+
- Pre-release versions like `1.0.0-rc.1` can be tagged, but syncing one to `trunk/` warns, since trunk is for the development version.
|
|
190
195
|
- `--trunk` without `--svn-tag` works but warns, because trunk then differs from the stable tag that WordPress.org serves downloads from.
|
|
191
196
|
|
|
192
197
|
### Exit codes
|
|
@@ -304,8 +309,8 @@ The `wpelevator-source` export condition points at `src/index.ts`. The tests and
|
|
|
304
309
|
|
|
305
310
|
| Tool | What it does | How `wp-release` differs |
|
|
306
311
|
|---|---|---|
|
|
307
|
-
| [10up WordPress.org plugin deploy](https://github.com/10up/action-wordpress-plugin-deploy) and [readme/asset update](https://github.com/10up/action-wordpress-plugin-asset-update) actions | Two separate GitHub Actions configured through env vars. A deploy always syncs the build to `trunk/` and copies it to the tag; readme and asset updates need the second action. Assets come from `.wordpress-org` by default, and files are selected with `.distignore` or `.gitattributes`. Files are synced with `rsync`. | One `deploy-svn` command with independent write flags, so a release, a
|
|
308
|
-
| [`grunt-wp-deploy`](https://github.com/stephenharris/grunt-wp-deploy) | Grunt task with `deploy_trunk` and `deploy_tag` booleans, interactive password prompts and a `Stable tag` check. | No Grunt dependency and never interactive.
|
|
312
|
+
| [10up WordPress.org plugin deploy](https://github.com/10up/action-wordpress-plugin-deploy) and [readme/asset update](https://github.com/10up/action-wordpress-plugin-asset-update) actions | Two separate GitHub Actions configured through env vars. A deploy always syncs the build to `trunk/` and copies it to the tag; readme and asset updates need the second action. Assets come from `.wordpress-org` by default, and files are selected with `.distignore` or `.gitattributes`. Files are synced with `rsync`. | One `deploy-svn` command with independent write flags, so a release, a readme-only update and an assets-only update are the same command with different flags. Runs locally and in any CI, not only GitHub Actions, and syncs in Node.js without `rsync`. Checks that the `Version` header, readme `Stable tag` and SVN tag agree before writing, which the 10up actions don't. Assets are deployed only when `--assets-dir` is passed, instead of always syncing `.wordpress-org` when it exists, so a plugin's own `assets/` folder is never uploaded by accident. Adds `--exclude` for patterns without an ignore file and `--from-zip` to deploy the exact files of a ZIP. |
|
|
313
|
+
| [`grunt-wp-deploy`](https://github.com/stephenharris/grunt-wp-deploy) | Grunt task with `deploy_trunk` and `deploy_tag` booleans, interactive password prompts and a `Stable tag` check. | No Grunt dependency and never interactive. `--readme-only` is a separate flag, where `grunt-wp-deploy` can only update trunk with the full build. Assets are independent of trunk writes. |
|
|
309
314
|
| [codeinwp theme deploy](https://github.com/codeinwp/action-wordpress-theme-deploy) | Fork of the 10up plugin action that commits themes to the themes SVN repository. | Doesn't deploy themes. Theme releases are ZIP uploads on WordPress.org; `zip` builds the upload with the theme folder as the root. |
|
|
310
315
|
| [`wp dist-archive`](https://github.com/wp-cli/dist-archive-command) | WP-CLI command that zips a project using `.distignore`, with `--plugin-dirname` and `--filename-format`. | Same `.distignore` file and `{name}.{version}` style filename format, but needs only Node.js instead of PHP and WP-CLI. `.distignore` is matched with full gitignore syntax, including `!` negation, and `--distignore` / `--exclude` let you point at another ignore file or add patterns on the command line. Builds are reproducible, and `--checksums` writes a manifest next to the ZIP. |
|
|
311
316
|
| [`wp plugin verify-checksums`](https://developer.wordpress.org/cli/commands/plugin/verify-checksums/) | WP-CLI command that checks installed plugins against the WordPress.org checksums API. | Reads the same manifest format, but from a file, so it also works for plugins and themes that aren't hosted on WordPress.org and for build directories in CI. `checksums` writes the manifest that WordPress.org generates for its own plugins. |
|
|
@@ -19,6 +19,7 @@ export function getDeployInputFromArgs(input) {
|
|
|
19
19
|
slug: getString(values, 'slug'),
|
|
20
20
|
version: getString(values, 'version'),
|
|
21
21
|
trunk: flag('trunk'),
|
|
22
|
+
readmeOnly: flag('readme-only'),
|
|
22
23
|
svnTag: getString(values, 'svn-tag'),
|
|
23
24
|
assets: getBoolean(values, 'no-assets') ? false : undefined,
|
|
24
25
|
assetsDir: getString(values, 'assets-dir'),
|
|
@@ -42,6 +43,7 @@ export default {
|
|
|
42
43
|
|
|
43
44
|
Writes (none by default, assets only with --assets-dir):
|
|
44
45
|
--trunk Sync the full source directory to trunk/
|
|
46
|
+
--readme-only Sync only the readme to trunk/ (not with --svn-tag)
|
|
45
47
|
--svn-tag <version> Copy trunk/ to tags/<version>, with or without
|
|
46
48
|
--trunk. A leading "v" is stripped.
|
|
47
49
|
--assets-dir <dir> Sync this directory with banners, icons and
|
|
@@ -70,11 +72,14 @@ or rejected.
|
|
|
70
72
|
Examples:
|
|
71
73
|
wp-release deploy-svn dist --trunk --svn-tag 1.2.0 --assets-dir .wordpress-org
|
|
72
74
|
Deploy 1.2.0 to trunk and the tag, and update the assets
|
|
75
|
+
wp-release deploy-svn dist --readme-only
|
|
76
|
+
Update only the readme
|
|
73
77
|
wp-release deploy-svn --assets-dir .wordpress-org
|
|
74
78
|
Update only the assets`,
|
|
75
79
|
options: {
|
|
76
80
|
...sourceDirArgs,
|
|
77
81
|
trunk: { type: 'boolean' },
|
|
82
|
+
'readme-only': { type: 'boolean' },
|
|
78
83
|
'svn-tag': { type: 'string' },
|
|
79
84
|
'assets-dir': { type: 'string' },
|
|
80
85
|
'no-assets': { type: 'boolean' },
|
package/dist/deploy-options.d.ts
CHANGED
|
@@ -13,6 +13,8 @@ export interface DeployInput {
|
|
|
13
13
|
version?: string;
|
|
14
14
|
/** Sync the full source directory to trunk/. */
|
|
15
15
|
trunk?: boolean;
|
|
16
|
+
/** Sync only the readme to trunk/. */
|
|
17
|
+
readmeOnly?: boolean;
|
|
16
18
|
/** Copy trunk/ to tags/<svnTag>. */
|
|
17
19
|
svnTag?: string;
|
|
18
20
|
/** Sync the assets directory, defaults to on when assetsDir is set. */
|
|
@@ -50,6 +52,7 @@ export interface DeployOptions extends FileSelection {
|
|
|
50
52
|
slug: string;
|
|
51
53
|
version: string | null;
|
|
52
54
|
trunk: boolean;
|
|
55
|
+
readmeOnly: boolean;
|
|
53
56
|
svnTag: string | null;
|
|
54
57
|
assets: boolean;
|
|
55
58
|
assetsDir: string | null;
|
|
@@ -117,7 +120,7 @@ export declare function getDeployOptionErrors(options: DeployOptions): string[];
|
|
|
117
120
|
*/
|
|
118
121
|
export declare function getDeployOptionWarnings(options: DeployOptions): string[];
|
|
119
122
|
/**
|
|
120
|
-
* Apply defaults to deploy options and validate them. Trunk and tag
|
|
123
|
+
* Apply defaults to deploy options and validate them. Trunk, readme and tag
|
|
121
124
|
* writes happen only when requested, and assets are synced whenever an
|
|
122
125
|
* assets directory is set, unless turned off. The version defaults to the
|
|
123
126
|
* SVN tag; without either, SvnDeploy reads the Version header of the
|
package/dist/deploy-options.js
CHANGED
|
@@ -62,9 +62,9 @@ function isValidFilename(name) {
|
|
|
62
62
|
*/
|
|
63
63
|
export function getDeployOptionErrors(options) {
|
|
64
64
|
const errors = [];
|
|
65
|
-
const { svnTag, version, assets, assetsDir, slug } = options;
|
|
66
|
-
if (
|
|
67
|
-
errors.push(
|
|
65
|
+
const { readmeOnly, svnTag, version, assets, assetsDir, slug } = options;
|
|
66
|
+
if (readmeOnly && svnTag) {
|
|
67
|
+
errors.push("--readme-only can't be combined with --svn-tag, since a tag is a release snapshot that a readme update never changes.");
|
|
68
68
|
}
|
|
69
69
|
if (svnTag && !isValidVersion(svnTag)) {
|
|
70
70
|
errors.push(`SVN tag "${svnTag}" isn't a valid version, use only letters, digits, dots, dashes, plus signs and underscores.`);
|
|
@@ -109,7 +109,7 @@ export function getDeployOptionWarnings(options) {
|
|
|
109
109
|
return warnings;
|
|
110
110
|
}
|
|
111
111
|
/**
|
|
112
|
-
* Apply defaults to deploy options and validate them. Trunk and tag
|
|
112
|
+
* Apply defaults to deploy options and validate them. Trunk, readme and tag
|
|
113
113
|
* writes happen only when requested, and assets are synced whenever an
|
|
114
114
|
* assets directory is set, unless turned off. The version defaults to the
|
|
115
115
|
* SVN tag; without either, SvnDeploy reads the Version header of the
|
|
@@ -130,6 +130,7 @@ export function resolveDeployOptions(input = {}) {
|
|
|
130
130
|
slug,
|
|
131
131
|
version: input.version ? normalizeTag(input.version) : svnTag,
|
|
132
132
|
trunk: Boolean(input.trunk),
|
|
133
|
+
readmeOnly: Boolean(input.readmeOnly),
|
|
133
134
|
assets: input.assets ?? Boolean(assetsDir),
|
|
134
135
|
svnTag,
|
|
135
136
|
sourceDir,
|
package/dist/svn-deploy.d.ts
CHANGED
|
@@ -73,7 +73,8 @@ export declare class SvnDeploy {
|
|
|
73
73
|
/**
|
|
74
74
|
* Check the plugin files before anything is written. A trunk sync needs
|
|
75
75
|
* a plugin with a Version header that matches the version, and with an
|
|
76
|
-
* SVN tag also a readme Stable tag that matches.
|
|
76
|
+
* SVN tag also a readme Stable tag that matches. Readme-only updates need
|
|
77
|
+
* the readme.
|
|
77
78
|
*
|
|
78
79
|
* @throws {ValidationError} When the files or versions don't match.
|
|
79
80
|
*/
|
|
@@ -184,7 +185,7 @@ export declare class SvnDeploy {
|
|
|
184
185
|
/**
|
|
185
186
|
* Check if the deploy reads plugin files, which assets-only runs don't.
|
|
186
187
|
*
|
|
187
|
-
* @return Whether trunk is written.
|
|
188
|
+
* @return Whether trunk or the readme is written.
|
|
188
189
|
*/
|
|
189
190
|
needsFiles(): boolean;
|
|
190
191
|
/**
|
package/dist/svn-deploy.js
CHANGED
|
@@ -9,7 +9,7 @@ import { CredentialsError, ValidationError } from "./errors.js";
|
|
|
9
9
|
import { loadFileRules, selectFiles } from "./file-selection.js";
|
|
10
10
|
import { readPackageMeta } from "./package-meta.js";
|
|
11
11
|
import { Svn } from "./svn.js";
|
|
12
|
-
import { syncDirectory } from "./sync.js";
|
|
12
|
+
import { copyFileIfChanged, syncDirectory } from "./sync.js";
|
|
13
13
|
import { extractZip } from "./unzip.js";
|
|
14
14
|
import { findVersionMismatches } from "./version-check.js";
|
|
15
15
|
/**
|
|
@@ -97,27 +97,35 @@ export class SvnDeploy {
|
|
|
97
97
|
/**
|
|
98
98
|
* Check the plugin files before anything is written. A trunk sync needs
|
|
99
99
|
* a plugin with a Version header that matches the version, and with an
|
|
100
|
-
* SVN tag also a readme Stable tag that matches.
|
|
100
|
+
* SVN tag also a readme Stable tag that matches. Readme-only updates need
|
|
101
|
+
* the readme.
|
|
101
102
|
*
|
|
102
103
|
* @throws {ValidationError} When the files or versions don't match.
|
|
103
104
|
*/
|
|
104
105
|
async checkVersions() {
|
|
105
|
-
const { trunk, svnTag, slug } = this.options;
|
|
106
|
+
const { trunk, readmeOnly, svnTag, slug, readme } = this.options;
|
|
106
107
|
const sourceDir = this.filesDir ?? this.options.sourceDir;
|
|
107
|
-
if (trunk) {
|
|
108
|
+
if (trunk || readmeOnly) {
|
|
108
109
|
const meta = await this.readPluginMeta(sourceDir);
|
|
109
|
-
|
|
110
|
-
sourceDir
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
110
|
+
if (readmeOnly && !meta.readme) {
|
|
111
|
+
throw new ValidationError(`${readme} doesn't exist in ${sourceDir}.`);
|
|
112
|
+
}
|
|
113
|
+
if (trunk) {
|
|
114
|
+
const { version, mismatches } = await findVersionMismatches({
|
|
115
|
+
sourceDir,
|
|
116
|
+
meta,
|
|
117
|
+
slug,
|
|
118
|
+
version: this.options.version,
|
|
119
|
+
stableTag: Boolean(svnTag),
|
|
120
|
+
});
|
|
121
|
+
this.version = version;
|
|
122
|
+
if (mismatches.length) {
|
|
123
|
+
throw new ValidationError(mismatches
|
|
124
|
+
.map(({ message }) => message)
|
|
125
|
+
.join('\n'));
|
|
126
|
+
}
|
|
127
|
+
this.logger.info(`Deploying version ${version}.`);
|
|
119
128
|
}
|
|
120
|
-
this.logger.info(`Deploying version ${version}.`);
|
|
121
129
|
}
|
|
122
130
|
}
|
|
123
131
|
/**
|
|
@@ -187,7 +195,7 @@ export class SvnDeploy {
|
|
|
187
195
|
* additions, deletions and asset MIME types, then copy trunk to the tag.
|
|
188
196
|
*/
|
|
189
197
|
async sync() {
|
|
190
|
-
const { trunk, assets } = this.options;
|
|
198
|
+
const { trunk, readmeOnly, assets, readme } = this.options;
|
|
191
199
|
const workingCopy = this.getWorkingCopy();
|
|
192
200
|
const sourceDir = this.filesDir ?? this.options.sourceDir;
|
|
193
201
|
if (trunk) {
|
|
@@ -197,6 +205,9 @@ export class SvnDeploy {
|
|
|
197
205
|
targetDir: join(workingCopy, 'trunk'),
|
|
198
206
|
});
|
|
199
207
|
}
|
|
208
|
+
if (readmeOnly) {
|
|
209
|
+
await copyFileIfChanged(join(sourceDir, readme), join(workingCopy, 'trunk', readme));
|
|
210
|
+
}
|
|
200
211
|
if (assets) {
|
|
201
212
|
await this.syncAssets();
|
|
202
213
|
}
|
|
@@ -367,7 +378,7 @@ export class SvnDeploy {
|
|
|
367
378
|
* @return Planned changes, in order.
|
|
368
379
|
*/
|
|
369
380
|
getPlan() {
|
|
370
|
-
const { svnUrl, trunk, assets, assetsDir, force } = this.options;
|
|
381
|
+
const { svnUrl, trunk, readmeOnly, assets, assetsDir, readme, force } = this.options;
|
|
371
382
|
const tagPath = this.getTagPath();
|
|
372
383
|
const message = this.options.message ?? this.getDefaultMessage();
|
|
373
384
|
const plan = [
|
|
@@ -377,6 +388,7 @@ export class SvnDeploy {
|
|
|
377
388
|
tagPath && !force && `Stop if ${tagPath} already exists`,
|
|
378
389
|
tagPath && force && `Replace ${tagPath} if it exists`,
|
|
379
390
|
trunk && `Sync ${this.describeSource()} to trunk/`,
|
|
391
|
+
readmeOnly && `Copy ${readme} to trunk/`,
|
|
380
392
|
tagPath && `Copy trunk/ to ${tagPath}`,
|
|
381
393
|
assets && `Sync ${assetsDir} to assets/`,
|
|
382
394
|
this.options.dryRun
|
|
@@ -392,9 +404,9 @@ export class SvnDeploy {
|
|
|
392
404
|
* @return Relative paths with their SVN checkout depth.
|
|
393
405
|
*/
|
|
394
406
|
getCheckoutPaths() {
|
|
395
|
-
const { trunk, svnTag, assets } = this.options;
|
|
407
|
+
const { trunk, readmeOnly, svnTag, assets } = this.options;
|
|
396
408
|
const paths = [];
|
|
397
|
-
if (trunk) {
|
|
409
|
+
if (trunk || readmeOnly) {
|
|
398
410
|
paths.push({ path: 'trunk', depth: 'infinity' });
|
|
399
411
|
}
|
|
400
412
|
if (svnTag) {
|
|
@@ -411,16 +423,16 @@ export class SvnDeploy {
|
|
|
411
423
|
* @return Whether to check out and commit.
|
|
412
424
|
*/
|
|
413
425
|
hasWrites() {
|
|
414
|
-
const { trunk, svnTag, assets } = this.options;
|
|
415
|
-
return Boolean(trunk || svnTag || assets);
|
|
426
|
+
const { trunk, readmeOnly, svnTag, assets } = this.options;
|
|
427
|
+
return Boolean(trunk || readmeOnly || svnTag || assets);
|
|
416
428
|
}
|
|
417
429
|
/**
|
|
418
430
|
* Check if the deploy reads plugin files, which assets-only runs don't.
|
|
419
431
|
*
|
|
420
|
-
* @return Whether trunk is written.
|
|
432
|
+
* @return Whether trunk or the readme is written.
|
|
421
433
|
*/
|
|
422
434
|
needsFiles() {
|
|
423
|
-
return this.options.trunk;
|
|
435
|
+
return this.options.trunk || this.options.readmeOnly;
|
|
424
436
|
}
|
|
425
437
|
/**
|
|
426
438
|
* Describe the files that are synced, including the ignore rules.
|
|
@@ -469,11 +481,15 @@ export class SvnDeploy {
|
|
|
469
481
|
return null;
|
|
470
482
|
}
|
|
471
483
|
getDefaultMessage() {
|
|
472
|
-
const { trunk, svnTag, assets } = this.options;
|
|
484
|
+
const { trunk, readmeOnly, svnTag, assets } = this.options;
|
|
473
485
|
if (svnTag) {
|
|
474
486
|
return `Release version ${svnTag}`;
|
|
475
487
|
}
|
|
476
|
-
const parts = [
|
|
488
|
+
const parts = [
|
|
489
|
+
trunk && 'trunk',
|
|
490
|
+
readmeOnly && 'readme',
|
|
491
|
+
assets && 'assets',
|
|
492
|
+
];
|
|
477
493
|
return `Update ${parts.filter(Boolean).join(' and ')}`;
|
|
478
494
|
}
|
|
479
495
|
}
|
package/package.json
CHANGED