wordpress-agent-kit 0.5.1 → 0.6.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/.agents/skills/wp-bootstrap/SKILL.md +314 -0
- package/.agents/skills/wp-bootstrap/references/composer-setup.md +275 -0
- package/.agents/skills/wp-bootstrap/references/monorepo-patterns.md +184 -0
- package/.agents/skills/wp-bootstrap/scripts/bootstrap.sh +151 -0
- package/.agents/skills/wp-bootstrap/scripts/detect-structure.mjs +466 -0
- package/.agents/skills/wp-bootstrap/scripts/package-wp.sh +173 -0
- package/.agents/skills/wp-bootstrap/scripts/playground-start.sh +148 -0
- package/.agents/skills/wp-bootstrap/scripts/playground-verify.sh +165 -0
- package/.agents/skills/wp-bootstrap/scripts/setup-github.sh +417 -0
- package/.agents/skills/wp-wpengine/SKILL.md +76 -12
- package/.agents/skills/wp-wpengine/references/github-actions-deploy.md +16 -9
- package/README.md +1 -1
- package/dist/cli.js +2 -0
- package/dist/commands/bootstrap.js +105 -0
- package/dist/lib/api.js +1 -0
- package/dist/lib/bootstrap.js +352 -0
- package/extensions/wp-agent-kit/index.ts +143 -3
- package/package.json +1 -1
- package/skills-custom/wp-bootstrap/SKILL.md +314 -0
- package/skills-custom/wp-bootstrap/references/composer-setup.md +275 -0
- package/skills-custom/wp-bootstrap/references/monorepo-patterns.md +184 -0
- package/skills-custom/wp-bootstrap/scripts/bootstrap.sh +151 -0
- package/skills-custom/wp-bootstrap/scripts/detect-structure.mjs +466 -0
- package/skills-custom/wp-bootstrap/scripts/package-wp.sh +173 -0
- package/skills-custom/wp-bootstrap/scripts/playground-start.sh +148 -0
- package/skills-custom/wp-bootstrap/scripts/playground-verify.sh +165 -0
- package/skills-custom/wp-bootstrap/scripts/setup-github.sh +417 -0
- package/skills-custom/wp-wpengine/SKILL.md +76 -12
- package/skills-custom/wp-wpengine/references/github-actions-deploy.md +16 -9
- package/.github/skills/blueprint/SKILL.md +0 -418
- package/.github/skills/wordpress-router/SKILL.md +0 -52
- package/.github/skills/wordpress-router/references/decision-tree.md +0 -55
- package/.github/skills/wp-abilities-api/SKILL.md +0 -108
- package/.github/skills/wp-abilities-api/references/delegate-helper-pattern.md +0 -241
- package/.github/skills/wp-abilities-api/references/domain-vs-projection.md +0 -113
- package/.github/skills/wp-abilities-api/references/error-code-vocabulary.md +0 -123
- package/.github/skills/wp-abilities-api/references/grouping-heuristic.md +0 -89
- package/.github/skills/wp-abilities-api/references/input-schema-gotchas.md +0 -265
- package/.github/skills/wp-abilities-api/references/php-registration.md +0 -94
- package/.github/skills/wp-abilities-api/references/plugin-family-patterns.md +0 -233
- package/.github/skills/wp-abilities-api/references/rest-api.md +0 -13
- package/.github/skills/wp-abilities-api/references/shared-core-service.md +0 -184
- package/.github/skills/wp-abilities-audit/SKILL.md +0 -199
- package/.github/skills/wp-abilities-audit/references/audit-schema.md +0 -300
- package/.github/skills/wp-abilities-audit/references/capability-gate-tracing.md +0 -197
- package/.github/skills/wp-abilities-audit/references/controller-enumeration.md +0 -116
- package/.github/skills/wp-abilities-verify/SKILL.md +0 -215
- package/.github/skills/wp-abilities-verify/references/annotation-correctness.md +0 -154
- package/.github/skills/wp-abilities-verify/references/audit-schema-validation.md +0 -131
- package/.github/skills/wp-abilities-verify/references/permission-roundtrip.md +0 -190
- package/.github/skills/wp-abilities-verify/references/runtime-harness.md +0 -462
- package/.github/skills/wp-abilities-verify/references/schema-lints.md +0 -118
- package/.github/skills/wp-abilities-verify/references/static-enumeration.md +0 -126
- package/.github/skills/wp-block-development/SKILL.md +0 -175
- package/.github/skills/wp-block-development/references/attributes-and-serialization.md +0 -22
- package/.github/skills/wp-block-development/references/block-json.md +0 -49
- package/.github/skills/wp-block-development/references/creating-new-blocks.md +0 -46
- package/.github/skills/wp-block-development/references/debugging.md +0 -36
- package/.github/skills/wp-block-development/references/deprecations.md +0 -24
- package/.github/skills/wp-block-development/references/dynamic-rendering.md +0 -23
- package/.github/skills/wp-block-development/references/inner-blocks.md +0 -25
- package/.github/skills/wp-block-development/references/registration.md +0 -30
- package/.github/skills/wp-block-development/references/supports-and-wrappers.md +0 -18
- package/.github/skills/wp-block-development/references/tooling-and-testing.md +0 -21
- package/.github/skills/wp-block-development/scripts/list_blocks.mjs +0 -121
- package/.github/skills/wp-block-themes/SKILL.md +0 -117
- package/.github/skills/wp-block-themes/references/creating-new-block-theme.md +0 -37
- package/.github/skills/wp-block-themes/references/debugging.md +0 -24
- package/.github/skills/wp-block-themes/references/patterns.md +0 -18
- package/.github/skills/wp-block-themes/references/style-variations.md +0 -14
- package/.github/skills/wp-block-themes/references/templates-and-parts.md +0 -16
- package/.github/skills/wp-block-themes/references/theme-json.md +0 -59
- package/.github/skills/wp-block-themes/scripts/detect_block_themes.mjs +0 -117
- package/.github/skills/wp-interactivity-api/SKILL.md +0 -180
- package/.github/skills/wp-interactivity-api/references/debugging.md +0 -29
- package/.github/skills/wp-interactivity-api/references/directives-quickref.md +0 -30
- package/.github/skills/wp-interactivity-api/references/server-side-rendering.md +0 -310
- package/.github/skills/wp-performance/SKILL.md +0 -147
- package/.github/skills/wp-performance/references/autoload-options.md +0 -24
- package/.github/skills/wp-performance/references/cron.md +0 -20
- package/.github/skills/wp-performance/references/database.md +0 -20
- package/.github/skills/wp-performance/references/http-api.md +0 -15
- package/.github/skills/wp-performance/references/measurement.md +0 -21
- package/.github/skills/wp-performance/references/object-cache.md +0 -24
- package/.github/skills/wp-performance/references/query-monitor-headless.md +0 -38
- package/.github/skills/wp-performance/references/server-timing.md +0 -22
- package/.github/skills/wp-performance/references/wp-cli-doctor.md +0 -24
- package/.github/skills/wp-performance/references/wp-cli-profile.md +0 -32
- package/.github/skills/wp-performance/scripts/perf_inspect.mjs +0 -128
- package/.github/skills/wp-phpstan/SKILL.md +0 -98
- package/.github/skills/wp-phpstan/references/configuration.md +0 -52
- package/.github/skills/wp-phpstan/references/third-party-classes.md +0 -76
- package/.github/skills/wp-phpstan/references/wordpress-annotations.md +0 -124
- package/.github/skills/wp-phpstan/scripts/phpstan_inspect.mjs +0 -263
- package/.github/skills/wp-playground/SKILL.md +0 -233
- package/.github/skills/wp-playground/references/blueprints.md +0 -36
- package/.github/skills/wp-playground/references/cli-commands.md +0 -39
- package/.github/skills/wp-playground/references/debugging.md +0 -16
- package/.github/skills/wp-playground/references/e2e-playwright.md +0 -115
- package/.github/skills/wp-plugin-development/SKILL.md +0 -113
- package/.github/skills/wp-plugin-development/references/data-and-cron.md +0 -19
- package/.github/skills/wp-plugin-development/references/debugging.md +0 -19
- package/.github/skills/wp-plugin-development/references/lifecycle.md +0 -33
- package/.github/skills/wp-plugin-development/references/security.md +0 -29
- package/.github/skills/wp-plugin-development/references/settings-api.md +0 -22
- package/.github/skills/wp-plugin-development/references/structure.md +0 -16
- package/.github/skills/wp-plugin-development/scripts/detect_plugins.mjs +0 -122
- package/.github/skills/wp-plugin-directory-guidelines/SKILL.md +0 -133
- package/.github/skills/wp-plugin-directory-guidelines/references/gpl-compliance.md +0 -217
- package/.github/skills/wp-plugin-directory-guidelines/references/guideline-review-checklist.md +0 -592
- package/.github/skills/wp-plugin-directory-guidelines/references/naming-rules.md +0 -121
- package/.github/skills/wp-project-triage/SKILL.md +0 -39
- package/.github/skills/wp-project-triage/references/triage.schema.json +0 -143
- package/.github/skills/wp-project-triage/scripts/detect_wp_project.mjs +0 -610
- package/.github/skills/wp-rest-api/SKILL.md +0 -115
- package/.github/skills/wp-rest-api/references/authentication.md +0 -18
- package/.github/skills/wp-rest-api/references/custom-content-types.md +0 -20
- package/.github/skills/wp-rest-api/references/discovery-and-params.md +0 -20
- package/.github/skills/wp-rest-api/references/responses-and-fields.md +0 -30
- package/.github/skills/wp-rest-api/references/routes-and-endpoints.md +0 -36
- package/.github/skills/wp-rest-api/references/schema.md +0 -22
- package/.github/skills/wp-wpcli-and-ops/SKILL.md +0 -124
- package/.github/skills/wp-wpcli-and-ops/references/automation.md +0 -30
- package/.github/skills/wp-wpcli-and-ops/references/cron-and-cache.md +0 -23
- package/.github/skills/wp-wpcli-and-ops/references/debugging.md +0 -17
- package/.github/skills/wp-wpcli-and-ops/references/multisite.md +0 -22
- package/.github/skills/wp-wpcli-and-ops/references/packages-and-updates.md +0 -22
- package/.github/skills/wp-wpcli-and-ops/references/safety.md +0 -30
- package/.github/skills/wp-wpcli-and-ops/references/search-replace.md +0 -40
- package/.github/skills/wp-wpcli-and-ops/scripts/wpcli_inspect.mjs +0 -90
- package/.github/skills/wp-wpengine/SKILL.md +0 -127
- package/.github/skills/wpds/SKILL.md +0 -59
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# setup-github.sh — configure GitHub repo for WP Engine CI/CD using the gh CLI.
|
|
3
|
+
#
|
|
4
|
+
# Checks authentication, reports missing secrets, sets them interactively or
|
|
5
|
+
# from provided values, and configures branch protection for deploy branches.
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
# bash .agents/skills/wp-bootstrap/scripts/setup-github.sh [OPTIONS]
|
|
9
|
+
#
|
|
10
|
+
# Options:
|
|
11
|
+
# --check-only Report status without making any changes (default if no --set-*)
|
|
12
|
+
# --set-secrets Interactively set missing WP Engine secrets
|
|
13
|
+
# --set-protection Configure branch protection for main/staging/develop
|
|
14
|
+
# --set-all Set secrets + branch protection
|
|
15
|
+
# --wpe-key=<file> Path to WP Engine SSH private key (default: ~/.ssh/wpengine_ed25519)
|
|
16
|
+
# --wpe-prod=<slug> WP Engine production install slug
|
|
17
|
+
# --wpe-staging=<slug> WP Engine staging install slug
|
|
18
|
+
# --wpe-dev=<slug> WP Engine dev install slug
|
|
19
|
+
# --no-confirm Skip confirmation prompts (use with care)
|
|
20
|
+
#
|
|
21
|
+
# Requires: gh CLI installed and authenticated (gh auth login)
|
|
22
|
+
#
|
|
23
|
+
# Exit codes:
|
|
24
|
+
# 0 All checks passed / actions completed
|
|
25
|
+
# 1 Error or user cancelled
|
|
26
|
+
# 2 gh CLI not installed or not authenticated
|
|
27
|
+
|
|
28
|
+
set -uo pipefail
|
|
29
|
+
|
|
30
|
+
# ── Parse args ────────────────────────────────────────────────────────────────
|
|
31
|
+
CHECK_ONLY=true
|
|
32
|
+
SET_SECRETS=false
|
|
33
|
+
SET_PROTECTION=false
|
|
34
|
+
WPE_KEY_FILE="${HOME}/.ssh/wpengine_ed25519"
|
|
35
|
+
WPE_PROD=""
|
|
36
|
+
WPE_STAGING=""
|
|
37
|
+
WPE_DEV=""
|
|
38
|
+
NO_CONFIRM=false
|
|
39
|
+
|
|
40
|
+
for arg in "$@"; do
|
|
41
|
+
case "$arg" in
|
|
42
|
+
--check-only) CHECK_ONLY=true ;;
|
|
43
|
+
--set-secrets) SET_SECRETS=true; CHECK_ONLY=false ;;
|
|
44
|
+
--set-protection) SET_PROTECTION=true; CHECK_ONLY=false ;;
|
|
45
|
+
--set-all) SET_SECRETS=true; SET_PROTECTION=true; CHECK_ONLY=false ;;
|
|
46
|
+
--wpe-key=*) WPE_KEY_FILE="${arg#--wpe-key=}" ;;
|
|
47
|
+
--wpe-prod=*) WPE_PROD="${arg#--wpe-prod=}" ;;
|
|
48
|
+
--wpe-staging=*) WPE_STAGING="${arg#--wpe-staging=}" ;;
|
|
49
|
+
--wpe-dev=*) WPE_DEV="${arg#--wpe-dev=}" ;;
|
|
50
|
+
--no-confirm) NO_CONFIRM=true ;;
|
|
51
|
+
esac
|
|
52
|
+
done
|
|
53
|
+
|
|
54
|
+
# ── Helpers ───────────────────────────────────────────────────────────────────
|
|
55
|
+
ok() { printf ' \033[32m✓\033[0m %s\n' "$*"; }
|
|
56
|
+
fail() { printf ' \033[31m✗\033[0m %s\n' "$*" >&2; }
|
|
57
|
+
warn() { printf ' \033[33m⚠\033[0m %s\n' "$*"; }
|
|
58
|
+
info() { printf ' \033[34m→\033[0m %s\n' "$*"; }
|
|
59
|
+
sep() { printf '\n\033[1m── %s\033[0m\n' "$*"; }
|
|
60
|
+
|
|
61
|
+
confirm() {
|
|
62
|
+
local prompt="${1} [y/N] "
|
|
63
|
+
$NO_CONFIRM && { echo "(auto-confirmed)"; return 0; }
|
|
64
|
+
read -r -p "$prompt" ans
|
|
65
|
+
[[ "${ans,,}" == "y" || "${ans,,}" == "yes" ]]
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
# ── 1. Check gh CLI ───────────────────────────────────────────────────────────
|
|
69
|
+
sep "GitHub CLI check"
|
|
70
|
+
|
|
71
|
+
if ! command -v gh >/dev/null 2>&1; then
|
|
72
|
+
fail "gh CLI not installed."
|
|
73
|
+
echo " Install: https://cli.github.com"
|
|
74
|
+
echo " macOS: brew install gh"
|
|
75
|
+
echo " Linux: sudo apt install gh (or see above URL)"
|
|
76
|
+
exit 2
|
|
77
|
+
fi
|
|
78
|
+
ok "gh $(gh --version | head -1 | awk '{print $3}')"
|
|
79
|
+
|
|
80
|
+
# ── 2. Check authentication ────────────────────────────────────────────────────
|
|
81
|
+
sep "Authentication"
|
|
82
|
+
|
|
83
|
+
AUTH_STATUS=$(gh auth status 2>&1)
|
|
84
|
+
if ! echo "$AUTH_STATUS" | grep -q "Logged in to github.com"; then
|
|
85
|
+
fail "Not authenticated. Run: gh auth login"
|
|
86
|
+
exit 2
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
ACCOUNT=$(echo "$AUTH_STATUS" | grep -o 'account [^ ]*' | awk '{print $2}' | head -1)
|
|
90
|
+
ok "Authenticated as @${ACCOUNT}"
|
|
91
|
+
|
|
92
|
+
# ── 3. Detect repo ────────────────────────────────────────────────────────────
|
|
93
|
+
sep "Repository"
|
|
94
|
+
|
|
95
|
+
ORIGIN=$(git remote get-url origin 2>/dev/null || echo "")
|
|
96
|
+
if [ -z "$ORIGIN" ]; then
|
|
97
|
+
fail "No 'origin' remote found. Is this a git repo with a GitHub remote?"
|
|
98
|
+
exit 1
|
|
99
|
+
fi
|
|
100
|
+
|
|
101
|
+
# Parse owner/repo from SSH or HTTPS URL
|
|
102
|
+
if [[ "$ORIGIN" =~ git@github\.com[:/]([^/]+)/([^.]+)(\.git)?$ ]]; then
|
|
103
|
+
OWNER="${BASH_REMATCH[1]}"
|
|
104
|
+
REPO="${BASH_REMATCH[2]}"
|
|
105
|
+
elif [[ "$ORIGIN" =~ https?://github\.com/([^/]+)/([^/.]+) ]]; then
|
|
106
|
+
OWNER="${BASH_REMATCH[1]}"
|
|
107
|
+
REPO="${BASH_REMATCH[2]}"
|
|
108
|
+
else
|
|
109
|
+
fail "Cannot parse GitHub owner/repo from remote: $ORIGIN"
|
|
110
|
+
exit 1
|
|
111
|
+
fi
|
|
112
|
+
|
|
113
|
+
# Verify repo is accessible
|
|
114
|
+
REPO_INFO=$(gh repo view "${OWNER}/${REPO}" --json name,owner,url,defaultBranchRef,visibility 2>&1)
|
|
115
|
+
if ! echo "$REPO_INFO" | grep -q '"name"'; then
|
|
116
|
+
fail "Cannot access repo ${OWNER}/${REPO}. Check permissions."
|
|
117
|
+
exit 1
|
|
118
|
+
fi
|
|
119
|
+
|
|
120
|
+
VISIBILITY=$(echo "$REPO_INFO" | python3 -c "import sys,json; print(json.load(sys.stdin)['visibility'])" 2>/dev/null || echo "unknown")
|
|
121
|
+
DEFAULT_BRANCH=$(echo "$REPO_INFO" | python3 -c "import sys,json; print(json.load(sys.stdin)['defaultBranchRef']['name'])" 2>/dev/null || echo "main")
|
|
122
|
+
REPO_URL=$(echo "$REPO_INFO" | python3 -c "import sys,json; print(json.load(sys.stdin)['url'])" 2>/dev/null || echo "")
|
|
123
|
+
|
|
124
|
+
ok "${OWNER}/${REPO} (${VISIBILITY,,}) — ${REPO_URL}"
|
|
125
|
+
info "Default branch: ${DEFAULT_BRANCH}"
|
|
126
|
+
|
|
127
|
+
# ── 4. Check secrets ──────────────────────────────────────────────────────────
|
|
128
|
+
sep "GitHub Secrets"
|
|
129
|
+
|
|
130
|
+
EXISTING_JSON=$(gh secret list --repo "${OWNER}/${REPO}" --json name 2>/dev/null || echo "[]")
|
|
131
|
+
EXISTING_SECRETS=$(echo "$EXISTING_JSON" | python3 -c "
|
|
132
|
+
import sys,json
|
|
133
|
+
secrets = json.load(sys.stdin)
|
|
134
|
+
for s in secrets: print(s['name'])
|
|
135
|
+
" 2>/dev/null || echo "")
|
|
136
|
+
|
|
137
|
+
# Define required secrets and their descriptions
|
|
138
|
+
declare -A SECRET_DESC
|
|
139
|
+
SECRET_DESC[WPE_SSH_KEY]="WP Engine SSH private key (contents of wpengine_ed25519)"
|
|
140
|
+
SECRET_DESC[WPE_SSH_KNOWN_HOSTS]="Known hosts for git.wpengine.com + ssh.wpengine.net"
|
|
141
|
+
SECRET_DESC[WPE_PROD_INSTALL]="Production install slug (e.g. mysite)"
|
|
142
|
+
SECRET_DESC[WPE_PROD_GIT_URL]="Production git push URL from WPE portal"
|
|
143
|
+
SECRET_DESC[WPE_STAGING_INSTALL]="Staging install slug (e.g. mysitestg)"
|
|
144
|
+
SECRET_DESC[WPE_STAGING_GIT_URL]="Staging git push URL from WPE portal"
|
|
145
|
+
SECRET_DESC[WPE_DEV_INSTALL]="Development install slug (e.g. mysitedev)"
|
|
146
|
+
SECRET_DESC[WPE_DEV_GIT_URL]="Development git push URL from WPE portal"
|
|
147
|
+
SECRET_DESC[WPE_API_USER]="WP Engine API username (from my.wpengine.com/api_access)"
|
|
148
|
+
SECRET_DESC[WPE_API_PASSWORD]="WP Engine API password"
|
|
149
|
+
SECRET_DESC[SLACK_WEBHOOK_URL]="Slack incoming webhook URL (optional)"
|
|
150
|
+
|
|
151
|
+
REQUIRED_SECRETS=(
|
|
152
|
+
WPE_SSH_KEY WPE_SSH_KNOWN_HOSTS
|
|
153
|
+
WPE_PROD_INSTALL WPE_PROD_GIT_URL
|
|
154
|
+
WPE_STAGING_INSTALL WPE_STAGING_GIT_URL
|
|
155
|
+
WPE_DEV_INSTALL WPE_DEV_GIT_URL
|
|
156
|
+
WPE_API_USER WPE_API_PASSWORD
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
MISSING_SECRETS=()
|
|
160
|
+
for secret in "${REQUIRED_SECRETS[@]}"; do
|
|
161
|
+
if echo "$EXISTING_SECRETS" | grep -qx "$secret"; then
|
|
162
|
+
ok "$secret"
|
|
163
|
+
else
|
|
164
|
+
warn "$secret — MISSING"
|
|
165
|
+
MISSING_SECRETS+=("$secret")
|
|
166
|
+
fi
|
|
167
|
+
done
|
|
168
|
+
|
|
169
|
+
# Optional
|
|
170
|
+
if echo "$EXISTING_SECRETS" | grep -qx "SLACK_WEBHOOK_URL"; then
|
|
171
|
+
ok "SLACK_WEBHOOK_URL (optional)"
|
|
172
|
+
else
|
|
173
|
+
info "SLACK_WEBHOOK_URL — not set (optional)"
|
|
174
|
+
fi
|
|
175
|
+
|
|
176
|
+
echo ""
|
|
177
|
+
if [ "${#MISSING_SECRETS[@]}" -eq 0 ]; then
|
|
178
|
+
ok "All required secrets are set ✓"
|
|
179
|
+
else
|
|
180
|
+
warn "${#MISSING_SECRETS[@]} secret(s) missing — run with --set-secrets to configure"
|
|
181
|
+
fi
|
|
182
|
+
|
|
183
|
+
# ── 5. Set missing secrets ────────────────────────────────────────────────────
|
|
184
|
+
if $SET_SECRETS && [ "${#MISSING_SECRETS[@]}" -gt 0 ]; then
|
|
185
|
+
sep "Setting missing secrets"
|
|
186
|
+
|
|
187
|
+
for secret in "${MISSING_SECRETS[@]}"; do
|
|
188
|
+
echo ""
|
|
189
|
+
info "Setting: ${secret}"
|
|
190
|
+
info "Purpose: ${SECRET_DESC[$secret]}"
|
|
191
|
+
|
|
192
|
+
VALUE=""
|
|
193
|
+
|
|
194
|
+
case "$secret" in
|
|
195
|
+
WPE_SSH_KEY)
|
|
196
|
+
if [ -f "$WPE_KEY_FILE" ]; then
|
|
197
|
+
info "Reading from $WPE_KEY_FILE"
|
|
198
|
+
if confirm " Set WPE_SSH_KEY from $WPE_KEY_FILE?"; then
|
|
199
|
+
VALUE=$(cat "$WPE_KEY_FILE")
|
|
200
|
+
fi
|
|
201
|
+
else
|
|
202
|
+
warn "Key file not found: $WPE_KEY_FILE"
|
|
203
|
+
info "Alternatives:"
|
|
204
|
+
info " 1. op read 'op://Employee/wpengine_ed25519/private key' > ~/.ssh/wpengine_ed25519"
|
|
205
|
+
info " 2. Paste the key manually below (enter blank line when done)"
|
|
206
|
+
if confirm " Enter key manually?"; then
|
|
207
|
+
LINES=()
|
|
208
|
+
echo " Paste private key (empty line to finish):"
|
|
209
|
+
while IFS= read -r line; do
|
|
210
|
+
[ -z "$line" ] && break
|
|
211
|
+
LINES+=("$line")
|
|
212
|
+
done
|
|
213
|
+
VALUE=$(printf '%s\n' "${LINES[@]}")
|
|
214
|
+
fi
|
|
215
|
+
fi
|
|
216
|
+
;;
|
|
217
|
+
|
|
218
|
+
WPE_SSH_KNOWN_HOSTS)
|
|
219
|
+
info "Generating from ssh-keyscan..."
|
|
220
|
+
VALUE=$(
|
|
221
|
+
{
|
|
222
|
+
# git push host — RSA key
|
|
223
|
+
ssh-keyscan -t rsa git.wpengine.com 2>/dev/null
|
|
224
|
+
# Include hashed entry for git.wpengine.com too
|
|
225
|
+
ssh-keyscan -H git.wpengine.com 2>/dev/null
|
|
226
|
+
# Note: SSH gateway subdomains ({install}.ssh.wpengine.net) use
|
|
227
|
+
# StrictHostKeyChecking=accept-new in the workflow SSH config,
|
|
228
|
+
# so they don't need pre-scanned entries here.
|
|
229
|
+
}
|
|
230
|
+
)
|
|
231
|
+
if [ -n "$VALUE" ]; then
|
|
232
|
+
info "Generated $(echo "$VALUE" | wc -l) known_hosts entries"
|
|
233
|
+
info "Gateway subdomains auto-accepted via StrictHostKeyChecking=accept-new"
|
|
234
|
+
confirm " Set WPE_SSH_KNOWN_HOSTS?" && true || VALUE=""
|
|
235
|
+
else
|
|
236
|
+
warn "ssh-keyscan failed — check network connectivity"
|
|
237
|
+
fi
|
|
238
|
+
;;
|
|
239
|
+
|
|
240
|
+
WPE_PROD_INSTALL)
|
|
241
|
+
[ -n "$WPE_PROD" ] && VALUE="$WPE_PROD" || {
|
|
242
|
+
read -r -p " Production install slug (e.g. mysite): " VALUE
|
|
243
|
+
}
|
|
244
|
+
;;
|
|
245
|
+
|
|
246
|
+
WPE_PROD_GIT_URL)
|
|
247
|
+
SLUG="${WPE_PROD:-}"
|
|
248
|
+
if [ -z "$SLUG" ]; then
|
|
249
|
+
# Try to get from wp-cli.yml
|
|
250
|
+
SLUG=$(grep -A2 '@production' wp-cli.yml 2>/dev/null | grep 'ssh:' | awk '{print $2}' | cut -d@ -f1 || echo "")
|
|
251
|
+
fi
|
|
252
|
+
info "Get exact URL from: https://my.wpengine.com/installs/${SLUG:-<install>}/git_push"
|
|
253
|
+
read -r -p " Production git URL (e.g. git@git.wpengine.com:mysite.git): " VALUE
|
|
254
|
+
;;
|
|
255
|
+
|
|
256
|
+
WPE_STAGING_INSTALL)
|
|
257
|
+
[ -n "$WPE_STAGING" ] && VALUE="$WPE_STAGING" || {
|
|
258
|
+
read -r -p " Staging install slug (e.g. mysitestg): " VALUE
|
|
259
|
+
}
|
|
260
|
+
;;
|
|
261
|
+
|
|
262
|
+
WPE_STAGING_GIT_URL)
|
|
263
|
+
SLUG="${WPE_STAGING:-}"
|
|
264
|
+
info "Get exact URL from: https://my.wpengine.com/installs/${SLUG:-<install>}/git_push"
|
|
265
|
+
read -r -p " Staging git URL (e.g. git@git.wpengine.com:mysitestg.git): " VALUE
|
|
266
|
+
;;
|
|
267
|
+
|
|
268
|
+
WPE_DEV_INSTALL)
|
|
269
|
+
[ -n "$WPE_DEV" ] && VALUE="$WPE_DEV" || {
|
|
270
|
+
read -r -p " Dev install slug (e.g. mysitedev): " VALUE
|
|
271
|
+
}
|
|
272
|
+
;;
|
|
273
|
+
|
|
274
|
+
WPE_DEV_GIT_URL)
|
|
275
|
+
SLUG="${WPE_DEV:-}"
|
|
276
|
+
info "Get exact URL from: https://my.wpengine.com/installs/${SLUG:-<install>}/git_push"
|
|
277
|
+
read -r -p " Dev git URL (e.g. git@git.wpengine.com:mysitedev.git): " VALUE
|
|
278
|
+
;;
|
|
279
|
+
|
|
280
|
+
WPE_API_USER)
|
|
281
|
+
info "Find at: https://my.wpengine.com/api_access"
|
|
282
|
+
read -r -p " WP Engine API username: " VALUE
|
|
283
|
+
;;
|
|
284
|
+
|
|
285
|
+
WPE_API_PASSWORD)
|
|
286
|
+
info "Find at: https://my.wpengine.com/api_access"
|
|
287
|
+
read -r -s -p " WP Engine API password (hidden): " VALUE
|
|
288
|
+
echo ""
|
|
289
|
+
;;
|
|
290
|
+
esac
|
|
291
|
+
|
|
292
|
+
if [ -n "$VALUE" ]; then
|
|
293
|
+
echo "$VALUE" | gh secret set "$secret" --repo "${OWNER}/${REPO}"
|
|
294
|
+
ok "$secret set"
|
|
295
|
+
else
|
|
296
|
+
warn "$secret skipped"
|
|
297
|
+
fi
|
|
298
|
+
done
|
|
299
|
+
fi
|
|
300
|
+
|
|
301
|
+
# ── 6. Branch protection ──────────────────────────────────────────────────────
|
|
302
|
+
sep "Branch Protection"
|
|
303
|
+
|
|
304
|
+
check_branch_protection() {
|
|
305
|
+
local branch="$1"
|
|
306
|
+
local prot
|
|
307
|
+
prot=$(gh api "repos/${OWNER}/${REPO}/branches/${branch}/protection" 2>/dev/null || echo "")
|
|
308
|
+
if [ -z "$prot" ] || echo "$prot" | grep -q '"message"'; then
|
|
309
|
+
warn "${branch}: not protected"
|
|
310
|
+
return 1
|
|
311
|
+
fi
|
|
312
|
+
local checks
|
|
313
|
+
checks=$(echo "$prot" | python3 -c "
|
|
314
|
+
import sys,json
|
|
315
|
+
p = json.load(sys.stdin)
|
|
316
|
+
checks = p.get('required_status_checks',{}).get('contexts',[])
|
|
317
|
+
reviews = p.get('required_pull_request_reviews',{}).get('required_approving_review_count',0)
|
|
318
|
+
print(f'status checks={checks}, reviewers={reviews}')
|
|
319
|
+
" 2>/dev/null || echo "configured")
|
|
320
|
+
ok "${branch}: protected (${checks})"
|
|
321
|
+
return 0
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
BRANCHES_NEEDING_PROTECTION=()
|
|
325
|
+
|
|
326
|
+
for branch in "$DEFAULT_BRANCH" "staging" "develop"; do
|
|
327
|
+
if ! check_branch_protection "$branch" 2>/dev/null; then
|
|
328
|
+
BRANCHES_NEEDING_PROTECTION+=("$branch")
|
|
329
|
+
fi
|
|
330
|
+
done
|
|
331
|
+
|
|
332
|
+
if [ "${#BRANCHES_NEEDING_PROTECTION[@]}" -eq 0 ]; then
|
|
333
|
+
ok "Branch protection looks good"
|
|
334
|
+
elif ! $SET_PROTECTION; then
|
|
335
|
+
warn "${#BRANCHES_NEEDING_PROTECTION[@]} branch(es) not protected — run with --set-protection to configure"
|
|
336
|
+
fi
|
|
337
|
+
|
|
338
|
+
# ── 7. Apply branch protection ────────────────────────────────────────────────
|
|
339
|
+
if $SET_PROTECTION && [ "${#BRANCHES_NEEDING_PROTECTION[@]}" -gt 0 ]; then
|
|
340
|
+
sep "Configuring Branch Protection"
|
|
341
|
+
|
|
342
|
+
for branch in "${BRANCHES_NEEDING_PROTECTION[@]}"; do
|
|
343
|
+
echo ""
|
|
344
|
+
info "Configuring: ${branch}"
|
|
345
|
+
|
|
346
|
+
# Determine required reviewer count
|
|
347
|
+
if [ "$branch" = "$DEFAULT_BRANCH" ]; then
|
|
348
|
+
REVIEWERS=2 # Production needs 2
|
|
349
|
+
else
|
|
350
|
+
REVIEWERS=1 # Staging/develop needs 1
|
|
351
|
+
fi
|
|
352
|
+
|
|
353
|
+
# Required status checks — gate-passed is the canonical check from ci-gate.yml
|
|
354
|
+
CONTEXTS='["gate-passed"]'
|
|
355
|
+
|
|
356
|
+
# For production, also require staging-source-check
|
|
357
|
+
if [ "$branch" = "$DEFAULT_BRANCH" ]; then
|
|
358
|
+
CONTEXTS='["gate-passed","staging-source-check"]'
|
|
359
|
+
fi
|
|
360
|
+
|
|
361
|
+
if ! confirm " Set ${branch} protection (${REVIEWERS} reviewers, checks: ${CONTEXTS})?"; then
|
|
362
|
+
warn "${branch}: skipped"
|
|
363
|
+
continue
|
|
364
|
+
fi
|
|
365
|
+
|
|
366
|
+
PAYLOAD=$(python3 -c "
|
|
367
|
+
import json
|
|
368
|
+
contexts = ${CONTEXTS}
|
|
369
|
+
payload = {
|
|
370
|
+
'required_status_checks': {
|
|
371
|
+
'strict': True,
|
|
372
|
+
'contexts': contexts
|
|
373
|
+
},
|
|
374
|
+
'enforce_admins': True,
|
|
375
|
+
'required_pull_request_reviews': {
|
|
376
|
+
'dismiss_stale_reviews': True,
|
|
377
|
+
'require_code_owner_reviews': False,
|
|
378
|
+
'required_approving_review_count': ${REVIEWERS}
|
|
379
|
+
},
|
|
380
|
+
'restrictions': None,
|
|
381
|
+
'allow_force_pushes': False,
|
|
382
|
+
'allow_deletions': False
|
|
383
|
+
}
|
|
384
|
+
print(json.dumps(payload))
|
|
385
|
+
")
|
|
386
|
+
|
|
387
|
+
if echo "$PAYLOAD" | gh api "repos/${OWNER}/${REPO}/branches/${branch}/protection" \
|
|
388
|
+
--method PUT --input - >/dev/null 2>&1; then
|
|
389
|
+
ok "${branch}: protection configured (${REVIEWERS} reviewer(s), checks: ${CONTEXTS})"
|
|
390
|
+
else
|
|
391
|
+
fail "${branch}: failed to configure protection"
|
|
392
|
+
info "You may need admin access or a GitHub token with 'repo' scope"
|
|
393
|
+
fi
|
|
394
|
+
done
|
|
395
|
+
fi
|
|
396
|
+
|
|
397
|
+
# ── 8. Summary ────────────────────────────────────────────────────────────────
|
|
398
|
+
sep "Summary"
|
|
399
|
+
|
|
400
|
+
TOTAL_MISSING="${#MISSING_SECRETS[@]}"
|
|
401
|
+
TOTAL_UNPROTECTED="${#BRANCHES_NEEDING_PROTECTION[@]}"
|
|
402
|
+
|
|
403
|
+
if [ "$TOTAL_MISSING" -eq 0 ] && [ "$TOTAL_UNPROTECTED" -eq 0 ]; then
|
|
404
|
+
ok "GitHub repo is fully configured for WP Engine CI/CD"
|
|
405
|
+
ok "Secrets: all set | Branch protection: all configured"
|
|
406
|
+
else
|
|
407
|
+
[ "$TOTAL_MISSING" -gt 0 ] && warn "Secrets missing: $TOTAL_MISSING (run --set-secrets)"
|
|
408
|
+
[ "$TOTAL_UNPROTECTED" -gt 0 ] && warn "Branches unprotected: ${BRANCHES_NEEDING_PROTECTION[*]} (run --set-protection)"
|
|
409
|
+
echo ""
|
|
410
|
+
info "Re-run: bash ${0} --set-all"
|
|
411
|
+
fi
|
|
412
|
+
|
|
413
|
+
echo ""
|
|
414
|
+
info "GitHub Actions: https://github.com/${OWNER}/${REPO}/actions"
|
|
415
|
+
info "Secrets: https://github.com/${OWNER}/${REPO}/settings/secrets/actions"
|
|
416
|
+
info "Branch rules: https://github.com/${OWNER}/${REPO}/settings/branches"
|
|
417
|
+
echo ""
|
|
@@ -42,8 +42,10 @@ chmod 600 ~/.ssh/wpengine_ed25519
|
|
|
42
42
|
|
|
43
43
|
# Trust WP Engine git push host (RSA — what WP Engine's git.wpengine.com serves)
|
|
44
44
|
ssh-keyscan -t rsa git.wpengine.com >> ~/.ssh/known_hosts
|
|
45
|
-
#
|
|
46
|
-
|
|
45
|
+
# Gateway: scan the specific install hostname (each install has its own subdomain)
|
|
46
|
+
# Do this once per environment you connect to:
|
|
47
|
+
ssh-keyscan -H <install>.ssh.wpengine.net >> ~/.ssh/known_hosts
|
|
48
|
+
# e.g.: ssh-keyscan -H mysite.ssh.wpengine.net >> ~/.ssh/known_hosts
|
|
47
49
|
```
|
|
48
50
|
|
|
49
51
|
Add to `~/.ssh/config` (before any `Host *` block):
|
|
@@ -55,15 +57,18 @@ Host git.wpengine.com
|
|
|
55
57
|
IdentityFile ~/.ssh/wpengine_ed25519
|
|
56
58
|
IdentitiesOnly yes
|
|
57
59
|
|
|
58
|
-
# WP Engine SSH gateway (WP-CLI +
|
|
60
|
+
# WP Engine SSH gateway (WP-CLI + file transfer)
|
|
59
61
|
Host *.ssh.wpengine.net
|
|
60
62
|
IdentityFile ~/.ssh/wpengine_ed25519
|
|
61
63
|
IdentitiesOnly yes
|
|
62
64
|
ControlMaster auto
|
|
63
65
|
ControlPath ~/.ssh/wpe-%r@%h:%p
|
|
64
66
|
ControlPersist 10m
|
|
67
|
+
StrictHostKeyChecking accept-new
|
|
65
68
|
```
|
|
66
69
|
|
|
70
|
+
> **`StrictHostKeyChecking accept-new`**: automatically accepts and stores the host key on first connection, then rejects any change to that key (MITM protection). Safer than `no`; avoids having to manually `ssh-keyscan` each install hostname.
|
|
71
|
+
>
|
|
67
72
|
> **ControlMaster / ControlPersist**: multiplexes SSH connections so subsequent commands over the same gateway reuse the existing connection. Cuts per-command latency from ~2 s to ~100 ms for repeated WP-CLI invocations.
|
|
68
73
|
|
|
69
74
|
Verify git push access:
|
|
@@ -92,13 +97,19 @@ where `<environment>` is `production`, `staging`, or `development`.
|
|
|
92
97
|
|
|
93
98
|
```bash
|
|
94
99
|
# Production (copy exact URL from portal)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
#
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
#
|
|
101
|
-
git remote add wpengine-
|
|
100
|
+
# ⚠️ Always copy the exact URL from the WP Engine portal — formats vary by account:
|
|
101
|
+
# https://my.wpengine.com/installs/<ENV>/git_push
|
|
102
|
+
#
|
|
103
|
+
# Modern accounts (most common):
|
|
104
|
+
git remote add wpengine-prod git@git.wpengine.com:<install-name>.git
|
|
105
|
+
# Legacy accounts (some plans add an environment prefix):
|
|
106
|
+
# git remote add wpengine-prod git@git.wpengine.com:production/<install-name>.git
|
|
107
|
+
|
|
108
|
+
# Staging (check portal for exact URL)
|
|
109
|
+
git remote add wpengine-staging git@git.wpengine.com:<install-name>stg.git
|
|
110
|
+
|
|
111
|
+
# Development (check portal for exact URL)
|
|
112
|
+
git remote add wpengine-dev git@git.wpengine.com:<install-name>dev.git
|
|
102
113
|
```
|
|
103
114
|
|
|
104
115
|
Deploy:
|
|
@@ -179,6 +190,59 @@ wp @production search-replace 'old-domain.com' 'new-domain.com' --dry-run
|
|
|
179
190
|
|
|
180
191
|
> Commit `wp-cli.yml` to the repo so all team members and CI pipelines share the same remote aliases.
|
|
181
192
|
|
|
193
|
+
#### Method D — SCP / rsync for file transfer
|
|
194
|
+
|
|
195
|
+
The SSH gateway also accepts SCP and rsync (port 22). Use this to pull/push files without a full git push:
|
|
196
|
+
|
|
197
|
+
```bash
|
|
198
|
+
# SCP: download a file from the server
|
|
199
|
+
scp -P 22 <install>@<install>.ssh.wpengine.net:sites/<install>/wp-content/uploads/large-file.zip ./
|
|
200
|
+
|
|
201
|
+
# SCP: upload a file to the server
|
|
202
|
+
scp -P 22 ./my-patch.php <install>@<install>.ssh.wpengine.net:sites/<install>/wp-content/plugins/my-plugin/
|
|
203
|
+
|
|
204
|
+
# rsync: sync wp-content/uploads from production to local (read-only pull)
|
|
205
|
+
rsync -avz --progress \
|
|
206
|
+
-e "ssh -p 22" \
|
|
207
|
+
<install>@<install>.ssh.wpengine.net:sites/<install>/wp-content/uploads/ \
|
|
208
|
+
./local-uploads/
|
|
209
|
+
|
|
210
|
+
# rsync: push a theme to staging (careful with --delete)
|
|
211
|
+
rsync -avz --dry-run \
|
|
212
|
+
-e "ssh -p 22" \
|
|
213
|
+
./my-theme/ \
|
|
214
|
+
<install>stg@<install>stg.ssh.wpengine.net:sites/<install>stg/wp-content/themes/my-theme/
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
> **WP Engine server path**: WordPress root is `sites/<install>/` relative to the SSH home, or `/home/wpe-user/sites/<install>` as an absolute path. `wp-content/` lives inside that root.
|
|
218
|
+
|
|
219
|
+
#### Method E — Multiple commands via heredoc
|
|
220
|
+
|
|
221
|
+
Run several commands in one SSH session without reconnecting:
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
# Heredoc over SSH (most efficient — one connection for all commands)
|
|
225
|
+
ssh <install>@<install>.ssh.wpengine.net bash -s << 'EOF'
|
|
226
|
+
set -e
|
|
227
|
+
wp cache flush --skip-plugins --skip-themes
|
|
228
|
+
wp rewrite flush --skip-plugins --skip-themes
|
|
229
|
+
wp cron event run --due-now --skip-plugins --skip-themes
|
|
230
|
+
wp core version --skip-plugins --skip-themes
|
|
231
|
+
EOF
|
|
232
|
+
|
|
233
|
+
# Interactive WP-CLI commands need -t (pseudo-TTY allocation)
|
|
234
|
+
# e.g. wp shell for a REPL session
|
|
235
|
+
ssh -t <install>@<install>.ssh.wpengine.net wp shell
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
#### SSH gateway environment notes
|
|
239
|
+
|
|
240
|
+
- **Restricted shell**: The gateway provides a limited shell environment. WP-CLI, PHP, basic POSIX utilities (echo, cat, stat, du, find, grep) and rsync/SCP are available. Package installation (`apt`, `yum`), sudo, and arbitrary service management are **not** available.
|
|
241
|
+
- **PHP version**: Matches the PHP version configured for that WP Engine install. `php --version` to confirm.
|
|
242
|
+
- **WordPress path**: `~/sites/<install>/` (relative to SSH home) or `/home/wpe-user/sites/<install>` (absolute).
|
|
243
|
+
- **`--path` flag**: If WP-CLI returns "not a WordPress installation", add `--path=/home/wpe-user/sites/<install>` explicitly.
|
|
244
|
+
- **Legacy gateway**: `ssh.wpengine.net` (no subdomain) is the old generic gateway address. Current convention always uses `<install>.ssh.wpengine.net`.
|
|
245
|
+
|
|
182
246
|
---
|
|
183
247
|
|
|
184
248
|
### 4) Common remote WP-CLI operations
|
|
@@ -376,9 +440,9 @@ curl -fsSL https://raw.githubusercontent.com/wpengine/wpe-labs-platform-skills/m
|
|
|
376
440
|
| Symptom | Fix |
|
|
377
441
|
|---|---|
|
|
378
442
|
| `Host key verification failed` (git) | `ssh-keyscan git.wpengine.com >> ~/.ssh/known_hosts` |
|
|
379
|
-
| `Host key verification failed` (gateway) | `ssh-keyscan -H ssh.wpengine.net >> ~/.ssh/known_hosts` |
|
|
443
|
+
| `Host key verification failed` (gateway) | Run `ssh-keyscan -H <install>.ssh.wpengine.net >> ~/.ssh/known_hosts` for that specific install hostname. Or add `StrictHostKeyChecking accept-new` to the `*.ssh.wpengine.net` SSH config block — it will auto-accept on first connect. |
|
|
380
444
|
| `Permission denied` | Confirm key at `~/.ssh/wpengine_ed25519`, `chmod 600`. Check the key is registered under **SSH Keys** in the WP Engine portal (separate from git push keys). |
|
|
381
|
-
| `git push rejected` |
|
|
445
|
+
| `git push rejected` | Get the exact URL from the portal (`https://my.wpengine.com/installs/<ENV>/git_push`). URL format varies by account — copy it verbatim. |
|
|
382
446
|
| SSH gateway hangs | Kill stale ControlMaster socket: `ssh -O stop <install>@<install>.ssh.wpengine.net` |
|
|
383
447
|
| `wp: command not found` on gateway | WP Engine's WP-CLI path: try `php /usr/local/bin/wp` or contact WP Engine support |
|
|
384
448
|
| WP-CLI returns wrong site | Add `--path=/home/wpe-user/sites/<install>` explicitly |
|
|
@@ -83,17 +83,21 @@ Add under **Settings → Secrets and variables → Actions**:
|
|
|
83
83
|
| Secret | Value |
|
|
84
84
|
|--------|-------|
|
|
85
85
|
| `WPE_SSH_KEY` | Private key (contents of `wpengine_ed25519`) |
|
|
86
|
-
| `WPE_SSH_KNOWN_HOSTS` | Output of `ssh-keyscan -t rsa git.wpengine.com && ssh-keyscan -H
|
|
86
|
+
| `WPE_SSH_KNOWN_HOSTS` | Output of `ssh-keyscan -t rsa git.wpengine.com && ssh-keyscan -H git.wpengine.com` (git push host only; gateway subdomains use `StrictHostKeyChecking accept-new`) |
|
|
87
87
|
| `WPE_PROD_INSTALL` | Production install slug (e.g., `mysite`) |
|
|
88
|
+
| `WPE_PROD_GIT_URL` | Production git remote URL from portal (`git_push` page) |
|
|
88
89
|
| `WPE_STAGING_INSTALL` | Staging install slug (e.g., `mysitestg`) |
|
|
90
|
+
| `WPE_STAGING_GIT_URL` | Staging git remote URL from portal |
|
|
89
91
|
| `WPE_DEV_INSTALL` | Development install slug (e.g., `mysitedev`) |
|
|
92
|
+
| `WPE_DEV_GIT_URL` | Development git remote URL from portal |
|
|
90
93
|
| `WPE_API_USER` | WP Engine API username (for backup snapshots) |
|
|
91
94
|
| `WPE_API_PASSWORD` | WP Engine API password |
|
|
92
95
|
| `SLACK_WEBHOOK_URL` | Slack incoming webhook (optional, for notifications) |
|
|
93
96
|
|
|
94
97
|
Generate the known hosts value once and save:
|
|
95
98
|
```bash
|
|
96
|
-
{ ssh-keyscan -t rsa git.wpengine.com; ssh-keyscan -H
|
|
99
|
+
{ ssh-keyscan -t rsa git.wpengine.com; ssh-keyscan -H git.wpengine.com; } 2>/dev/null
|
|
100
|
+
# Note: SSH gateway subdomains use StrictHostKeyChecking=accept-new in workflows
|
|
97
101
|
```
|
|
98
102
|
|
|
99
103
|
---
|
|
@@ -254,7 +258,8 @@ jobs:
|
|
|
254
258
|
env:
|
|
255
259
|
INSTALL: ${{ secrets.WPE_DEV_INSTALL }}
|
|
256
260
|
run: |
|
|
257
|
-
|
|
261
|
+
# URL from portal: https://my.wpengine.com/installs/<ENV>/git_push (set WPE_DEV_GIT_URL secret)
|
|
262
|
+
git remote add wpe-dev "${WPE_DEV_GIT_URL:-git@git.wpengine.com:${INSTALL}.git}"
|
|
258
263
|
# Force-add built assets (normally gitignored)
|
|
259
264
|
git add -f dist/ build/ 2>/dev/null || true
|
|
260
265
|
git diff --cached --quiet || git commit -m "ci: add built assets [skip ci]"
|
|
@@ -264,7 +269,7 @@ jobs:
|
|
|
264
269
|
env:
|
|
265
270
|
INSTALL: ${{ secrets.WPE_DEV_INSTALL }}
|
|
266
271
|
run: |
|
|
267
|
-
ssh -o StrictHostKeyChecking=
|
|
272
|
+
ssh -o StrictHostKeyChecking=accept-new ${INSTALL}@${INSTALL}.ssh.wpengine.net \
|
|
268
273
|
wp cache flush --skip-plugins --skip-themes
|
|
269
274
|
```
|
|
270
275
|
|
|
@@ -355,7 +360,8 @@ jobs:
|
|
|
355
360
|
env:
|
|
356
361
|
INSTALL: ${{ secrets.WPE_STAGING_INSTALL }}
|
|
357
362
|
run: |
|
|
358
|
-
|
|
363
|
+
# URL from portal: set WPE_STAGING_GIT_URL secret
|
|
364
|
+
git remote add wpe-staging "${WPE_STAGING_GIT_URL:-git@git.wpengine.com:${INSTALL}.git}"
|
|
359
365
|
git add -f dist/ build/ 2>/dev/null || true
|
|
360
366
|
git diff --cached --quiet || git commit -m "ci: add built assets [skip ci]"
|
|
361
367
|
git push wpe-staging HEAD:main --force
|
|
@@ -364,7 +370,7 @@ jobs:
|
|
|
364
370
|
env:
|
|
365
371
|
INSTALL: ${{ secrets.WPE_STAGING_INSTALL }}
|
|
366
372
|
run: |
|
|
367
|
-
ssh -o StrictHostKeyChecking=
|
|
373
|
+
ssh -o StrictHostKeyChecking=accept-new ${INSTALL}@${INSTALL}.ssh.wpengine.net bash -s <<'EOF'
|
|
368
374
|
set -e
|
|
369
375
|
wp cache flush --skip-plugins --skip-themes
|
|
370
376
|
wp rewrite flush --skip-plugins --skip-themes
|
|
@@ -534,7 +540,8 @@ jobs:
|
|
|
534
540
|
env:
|
|
535
541
|
INSTALL: ${{ secrets.WPE_PROD_INSTALL }}
|
|
536
542
|
run: |
|
|
537
|
-
|
|
543
|
+
# URL from portal: set WPE_PROD_GIT_URL secret
|
|
544
|
+
git remote add wpe-prod "${WPE_PROD_GIT_URL:-git@git.wpengine.com:${INSTALL}.git}"
|
|
538
545
|
git add -f dist/ build/ 2>/dev/null || true
|
|
539
546
|
git diff --cached --quiet || git commit -m "ci: add built assets [skip ci]"
|
|
540
547
|
git push wpe-prod HEAD:main --force
|
|
@@ -543,7 +550,7 @@ jobs:
|
|
|
543
550
|
env:
|
|
544
551
|
INSTALL: ${{ secrets.WPE_PROD_INSTALL }}
|
|
545
552
|
run: |
|
|
546
|
-
ssh -o StrictHostKeyChecking=
|
|
553
|
+
ssh -o StrictHostKeyChecking=accept-new ${INSTALL}@${INSTALL}.ssh.wpengine.net bash -s <<'EOF'
|
|
547
554
|
set -e
|
|
548
555
|
wp cache flush --skip-plugins --skip-themes
|
|
549
556
|
wp rewrite flush --skip-plugins --skip-themes
|
|
@@ -603,7 +610,7 @@ jobs:
|
|
|
603
610
|
"https://${INSTALL}.wpenginepowered.com/" --max-time 30)
|
|
604
611
|
echo "Post-rollback status: HTTP $STATUS"
|
|
605
612
|
# Flush cache after rollback
|
|
606
|
-
ssh -o StrictHostKeyChecking=
|
|
613
|
+
ssh -o StrictHostKeyChecking=accept-new ${INSTALL}@${INSTALL}.ssh.wpengine.net \
|
|
607
614
|
wp cache flush --skip-plugins --skip-themes
|
|
608
615
|
echo "❌ Deployment was ROLLED BACK to $PREV_SHA"
|
|
609
616
|
exit 1 # Mark the job as failed so Slack notifies
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](LICENSE)
|
|
4
4
|
[](https://www.typescriptlang.org/)
|
|
5
|
-
[](package.json)
|
|
6
6
|
[](package.json)
|
|
7
7
|
[](.github/workflows/ci.yml)
|
|
8
8
|
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createRequire } from 'node:module';
|
|
3
3
|
import { Command } from 'commander';
|
|
4
|
+
import { bootstrapCommand } from './commands/bootstrap.js';
|
|
4
5
|
import { cleanSkillsCommand } from './commands/clean-skills.js';
|
|
5
6
|
import { installCommand } from './commands/install.js';
|
|
6
7
|
import { runPlaygroundCommand } from './commands/run-playground.js';
|
|
@@ -26,6 +27,7 @@ program
|
|
|
26
27
|
sortSubcommands: true,
|
|
27
28
|
});
|
|
28
29
|
// Add commands
|
|
30
|
+
program.addCommand(bootstrapCommand);
|
|
29
31
|
program.addCommand(cleanSkillsCommand);
|
|
30
32
|
program.addCommand(installCommand);
|
|
31
33
|
program.addCommand(setupCommand);
|