@johnbillion/plugin-infrastructure 2.0.0-beta.1
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/LICENSE +21 -0
- package/README.md +114 -0
- package/dist/acceptance/global-utils.d.ts +22 -0
- package/dist/acceptance/global-utils.js +51 -0
- package/dist/acceptance/index.d.ts +1 -0
- package/dist/acceptance/index.js +5 -0
- package/package.json +32 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 John Blackbourn
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Plugin Infrastructure
|
|
2
|
+
|
|
3
|
+
Reusable infrastructure relating to testing, building, linting, deploying, and verifying my WordPress plugins (see the "Used by" section below).
|
|
4
|
+
|
|
5
|
+
Provided without support, warranty, guarantee, backwards compatibility, fitness for purpose, resilience, safety, sanity, beauty, or support for any plugin that isn't one of mine.
|
|
6
|
+
|
|
7
|
+
## Used by
|
|
8
|
+
|
|
9
|
+
* [Extended CPTs](https://github.com/johnbillion/extended-cpts)
|
|
10
|
+
* [Query Monitor](https://github.com/johnbillion/query-monitor)
|
|
11
|
+
* [User Switching](https://github.com/johnbillion/user-switching)
|
|
12
|
+
* [WP Crontrol](https://github.com/johnbillion/wp-crontrol)
|
|
13
|
+
|
|
14
|
+
## Features
|
|
15
|
+
|
|
16
|
+
* Acceptance testing
|
|
17
|
+
* Integration testing
|
|
18
|
+
* Coding standards testing
|
|
19
|
+
* Static analysis
|
|
20
|
+
* Workflow file linting
|
|
21
|
+
* Deployment to WordPress.org
|
|
22
|
+
* Build provenance attestation
|
|
23
|
+
* SLSA v1.0 Build level 3 facilitation
|
|
24
|
+
* Ongoing supply chain assurance
|
|
25
|
+
|
|
26
|
+
Plugins that use this library all use a similar setup in their workflows:
|
|
27
|
+
|
|
28
|
+
## Acceptance testing
|
|
29
|
+
|
|
30
|
+
* Push to a main branch or pull request, `acceptance-tests.yml` fires
|
|
31
|
+
* Constructs a matrix of supported PHP and WordPress versions
|
|
32
|
+
* Uses `reusable-acceptance-tests.yml`
|
|
33
|
+
* Installs PHP and WordPress
|
|
34
|
+
* Runs the build
|
|
35
|
+
* Runs acceptance testing with Playwright
|
|
36
|
+
|
|
37
|
+
## Integration testing
|
|
38
|
+
|
|
39
|
+
* Push to a main branch or pull request, `integration-tests.yml` fires
|
|
40
|
+
* Constructs a matrix of supported PHP and WordPress versions
|
|
41
|
+
* Uses `reusable-integration-tests.yml`
|
|
42
|
+
* Installs PHP and WordPress
|
|
43
|
+
* Runs the build
|
|
44
|
+
* Runs integration testing with PHPUnit, once for:
|
|
45
|
+
* Single site
|
|
46
|
+
* Multisite
|
|
47
|
+
|
|
48
|
+
## Coding standards testing
|
|
49
|
+
|
|
50
|
+
* Push to a main branch or pull request, `coding-standards.yml` fires
|
|
51
|
+
* Uses `reusable-coding-standards.yml`
|
|
52
|
+
* Installs PHP
|
|
53
|
+
* Checks coding standards with PHPCS
|
|
54
|
+
|
|
55
|
+
## Static analysis
|
|
56
|
+
|
|
57
|
+
* Push to a main branch or pull request, `static-analysis.yml` fires
|
|
58
|
+
* Constructs a matrix of supported PHP versions
|
|
59
|
+
* Uses `reusable-static-analysis.yml`
|
|
60
|
+
* Installs PHP
|
|
61
|
+
* Runs static analysis with PHPStan
|
|
62
|
+
|
|
63
|
+
## Workflow file linting
|
|
64
|
+
|
|
65
|
+
* Push to a main branch or pull request, `lint-workflows.yml` fires
|
|
66
|
+
* Uses `reusable-workflow-lint.yml`
|
|
67
|
+
* Lints all GitHub Actions workflow files for correctness and security using:
|
|
68
|
+
* ActionLint
|
|
69
|
+
* Octoscan
|
|
70
|
+
* Zizmor
|
|
71
|
+
* Poutine
|
|
72
|
+
* Uploads results to GitHub Code Scanning
|
|
73
|
+
|
|
74
|
+
## Deployment
|
|
75
|
+
|
|
76
|
+
### WordPress.org
|
|
77
|
+
|
|
78
|
+
* Push to the `release` branch, `build.yml` fires
|
|
79
|
+
* Uses `reusable-build.yml`
|
|
80
|
+
* Runs the build
|
|
81
|
+
* Reads version from `package.json`
|
|
82
|
+
* Commits built files
|
|
83
|
+
* Pushes to `release-$VERSION`
|
|
84
|
+
* Tags the new version and pushes
|
|
85
|
+
* Creates a draft release
|
|
86
|
+
* Publish the release, `deploy-tag.yml` fires
|
|
87
|
+
* Uses `reusable-deploy-tag.yml`
|
|
88
|
+
* Creates a changelog entry from the release notes
|
|
89
|
+
* Uses `10up/action-wordpress-plugin-deploy`
|
|
90
|
+
* Deploys the new version to WordPress.org
|
|
91
|
+
* Generates a zip file
|
|
92
|
+
* Uses `johnbillion/action-wordpress-plugin-attestation`
|
|
93
|
+
* Fetches the zip from WordPress.org
|
|
94
|
+
* Generates a build provenance attestation if the zip contents matches the build
|
|
95
|
+
|
|
96
|
+
### Packagist
|
|
97
|
+
|
|
98
|
+
* Happens automatically with each release via the auto-update mechanism on Packagist.org.
|
|
99
|
+
* Always identical to the version deployed to WordPress.org
|
|
100
|
+
|
|
101
|
+
### GitHub
|
|
102
|
+
|
|
103
|
+
* Automatically closes the completed milestone for each release
|
|
104
|
+
* Automatically creates the next major, minor, and patch release milestones after each release
|
|
105
|
+
|
|
106
|
+
## Supply chain assurance
|
|
107
|
+
|
|
108
|
+
* Hourly scheduled workflow runs in `verify-distribution.yml`
|
|
109
|
+
* Uses `reusable-verify-distribution.yml`
|
|
110
|
+
* Verifies the provenance of the plugin on WordPress.org
|
|
111
|
+
|
|
112
|
+
## Licence
|
|
113
|
+
|
|
114
|
+
MIT
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface GlobalUtilsOptions {
|
|
2
|
+
baseURL: string;
|
|
3
|
+
pluginSlug: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class GlobalUtils {
|
|
6
|
+
private baseURL;
|
|
7
|
+
private pluginSlug;
|
|
8
|
+
constructor(options: GlobalUtilsOptions);
|
|
9
|
+
/**
|
|
10
|
+
* Run a WP-CLI command
|
|
11
|
+
*
|
|
12
|
+
* @throws Error if the command fails
|
|
13
|
+
*/
|
|
14
|
+
runWPCLICommand(command: string): string;
|
|
15
|
+
installWordPress(): void;
|
|
16
|
+
/**
|
|
17
|
+
* Check if current WordPress version meets minimum requirement
|
|
18
|
+
*
|
|
19
|
+
* @throws Error if unable to parse WordPress version
|
|
20
|
+
*/
|
|
21
|
+
isWordPressVersionAtLeast(minVersion: number): boolean;
|
|
22
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GlobalUtils = void 0;
|
|
4
|
+
class GlobalUtils {
|
|
5
|
+
constructor(options) {
|
|
6
|
+
this.baseURL = options.baseURL;
|
|
7
|
+
this.pluginSlug = options.pluginSlug;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Run a WP-CLI command
|
|
11
|
+
*
|
|
12
|
+
* @throws Error if the command fails
|
|
13
|
+
*/
|
|
14
|
+
runWPCLICommand(command) {
|
|
15
|
+
const { execSync } = require('child_process');
|
|
16
|
+
const fullCommand = `docker compose exec --user wp_php wpcli wp --url="${this.baseURL}" ${command}`;
|
|
17
|
+
try {
|
|
18
|
+
const stdout = execSync(fullCommand, { encoding: 'utf8', cwd: process.cwd() });
|
|
19
|
+
return stdout.trim();
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
throw new Error(`WP-CLI command failed: ${error.message}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
installWordPress() {
|
|
26
|
+
// Install WordPress:
|
|
27
|
+
this.runWPCLICommand('db reset --yes');
|
|
28
|
+
this.runWPCLICommand(`core install --title="${this.pluginSlug}" --admin_user="admin" --admin_password="password" --admin_email="admin@example.com" --skip-email`);
|
|
29
|
+
// Set a predictable permalink structure:
|
|
30
|
+
this.runWPCLICommand('rewrite structure "/%postname%/"');
|
|
31
|
+
// Activate the plugin under test:
|
|
32
|
+
this.runWPCLICommand(`plugin activate ${this.pluginSlug}`);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check if current WordPress version meets minimum requirement
|
|
36
|
+
*
|
|
37
|
+
* @throws Error if unable to parse WordPress version
|
|
38
|
+
*/
|
|
39
|
+
isWordPressVersionAtLeast(minVersion) {
|
|
40
|
+
const wpVersion = this.runWPCLICommand('core version');
|
|
41
|
+
// Extract major.minor version from WordPress version string
|
|
42
|
+
// Examples: "6.2.1" -> "6.2", "6.9-alpha-60684" -> "6.9"
|
|
43
|
+
const versionMatch = wpVersion.match(/^(\d+\.\d+)/);
|
|
44
|
+
if (!versionMatch) {
|
|
45
|
+
throw new Error(`Unable to parse WordPress version: ${wpVersion}`);
|
|
46
|
+
}
|
|
47
|
+
const currentVersion = parseFloat(versionMatch[1]);
|
|
48
|
+
return currentVersion >= minVersion;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.GlobalUtils = GlobalUtils;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { GlobalUtils, GlobalUtilsOptions } from './global-utils';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GlobalUtils = void 0;
|
|
4
|
+
var global_utils_1 = require("./global-utils");
|
|
5
|
+
Object.defineProperty(exports, "GlobalUtils", { enumerable: true, get: function () { return global_utils_1.GlobalUtils; } });
|
package/package.json
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@johnbillion/plugin-infrastructure",
|
|
3
|
+
"version": "2.0.0-beta.1",
|
|
4
|
+
"description": "Shared utilities for WordPress plugin development",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "John Blackbourn",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/johnbillion/plugin-infrastructure.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/johnbillion/plugin-infrastructure",
|
|
12
|
+
"exports": {
|
|
13
|
+
"./acceptance": {
|
|
14
|
+
"require": "./dist/acceptance/index.js",
|
|
15
|
+
"types": "./dist/acceptance/index.d.ts"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist"
|
|
20
|
+
],
|
|
21
|
+
"engines": {
|
|
22
|
+
"node": ">=18"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsc",
|
|
26
|
+
"prepublishOnly": "npm run build"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^24.3.0",
|
|
30
|
+
"typescript": "^5.9.2"
|
|
31
|
+
}
|
|
32
|
+
}
|