@mokoconsulting/mcp-mokosuite 1.0.0 → 1.1.0-dev.360
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/.mokogit/workflows/auto-bump.yml +8 -0
- package/.mokogit/workflows/auto-release.yml +184 -71
- package/.mokogit/workflows/cascade-dev.yml +128 -60
- package/.mokogit/workflows/changelog-validation.yml +41 -25
- package/.mokogit/workflows/ci-issue-reporter.yml +1 -1
- package/.mokogit/workflows/cleanup.yml +3 -3
- package/.mokogit/workflows/custom-workflow-sync-trigger.yml +83 -0
- package/.mokogit/workflows/issue-branch.yml +1 -1
- package/.mokogit/workflows/npm-build-test.yml +103 -19
- package/.mokogit/workflows/npm-prerelease.yml +174 -0
- package/.mokogit/workflows/npm-publish.yml +44 -17
- package/.mokogit/workflows/pr-check.yml +181 -53
- package/.mokogit/workflows/pre-release.yml +174 -35
- package/.mokogit/workflows/rc-revert.yml +1 -1
- package/.mokogit/workflows/version-set.yml +4 -4
- package/AGENTS.md +39 -0
- package/CHANGELOG.md +46 -10
- package/dist/index.js +28 -1
- package/docs/API.md +54 -45
- package/package.json +1 -1
- package/src/index.ts +59 -1
- package/.mokogit/workflows/ci-generic.yml +0 -203
- package/.mokogit/workflows/repo-health.yml +0 -700
- package/.mokogit/workflows/standards-compliance.yml +0 -2507
|
@@ -30,6 +30,13 @@ on:
|
|
|
30
30
|
- '.mokogit/**'
|
|
31
31
|
- '.gitea/**'
|
|
32
32
|
- '.github/**'
|
|
33
|
+
- '**/*.md'
|
|
34
|
+
- 'wiki/**'
|
|
35
|
+
- '.editorconfig'
|
|
36
|
+
- '.gitignore'
|
|
37
|
+
- '.gitattributes'
|
|
38
|
+
- '.gitmessage'
|
|
39
|
+
- 'LICENSE'
|
|
33
40
|
|
|
34
41
|
env:
|
|
35
42
|
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
|
|
@@ -61,6 +68,7 @@ jobs:
|
|
|
61
68
|
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer >/dev/null 2>&1
|
|
62
69
|
fi
|
|
63
70
|
if [ -d "/opt/mokocli/cli" ]; then
|
|
71
|
+
git -C /opt/mokocli pull --ff-only --quiet 2>/dev/null || echo " (mokocli auto-refresh skipped)"
|
|
64
72
|
echo "MOKO_CLI=/opt/mokocli/cli" >> "$GITHUB_ENV"
|
|
65
73
|
else
|
|
66
74
|
git clone --depth 1 --branch main --quiet \
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
# INGROUP: MokoCLI.Release
|
|
8
8
|
# REPO: https://git.mokoconsulting.tech/MokoConsulting/Template-Generic
|
|
9
9
|
# PATH: /.mokogit/workflows/auto-release.yml
|
|
10
|
-
# VERSION:
|
|
10
|
+
# VERSION: 06.02.00
|
|
11
11
|
# BRIEF: Universal build & release � detects platform from metadata API
|
|
12
12
|
#
|
|
13
13
|
# +=======================================================================+
|
|
@@ -25,20 +25,56 @@
|
|
|
25
25
|
name: "Universal: Build & Release"
|
|
26
26
|
|
|
27
27
|
on:
|
|
28
|
+
# RC preview: build a release-candidate when a PR to main is opened / updated.
|
|
28
29
|
pull_request:
|
|
29
30
|
types: [opened, synchronize, closed]
|
|
30
31
|
branches:
|
|
31
32
|
- main
|
|
32
33
|
paths-ignore:
|
|
33
|
-
- '.mokogit
|
|
34
|
-
- '
|
|
34
|
+
- '.mokogit/**'
|
|
35
|
+
- '.gitea/**'
|
|
36
|
+
- '.github/**'
|
|
37
|
+
- '.vscode/**'
|
|
38
|
+
- '.idea/**'
|
|
39
|
+
- 'docs/**'
|
|
35
40
|
- 'wiki/**'
|
|
41
|
+
- '**/*.md'
|
|
36
42
|
- '.editorconfig'
|
|
37
43
|
- '.gitignore'
|
|
38
44
|
- '.gitattributes'
|
|
45
|
+
- '.gitmodules'
|
|
39
46
|
- '.gitmessage'
|
|
40
|
-
- '
|
|
41
|
-
|
|
47
|
+
- 'phpstan.neon'
|
|
48
|
+
- 'LICENSE'
|
|
49
|
+
# Stable release on every PUSH to main (a merged promotion) — the same
|
|
50
|
+
# push-based principle as pre-release's dev-channel build. A push trigger is
|
|
51
|
+
# race-free vs the old pull_request:closed, which could miss its run when this
|
|
52
|
+
# workflow file re-synced from the template concurrently with the merge.
|
|
53
|
+
# Loop-safe: the workflow's own commits to main are either paths-ignored (the
|
|
54
|
+
# CHANGELOG promote step → **/*.md) or carry [skip ci] (mokocli's build commit
|
|
55
|
+
# + the changelog commit), and the release job's if: re-checks [skip ci], so a
|
|
56
|
+
# self-push never re-triggers a release. The non-code paths-ignore also means a
|
|
57
|
+
# docs/CI-only push to main does not release.
|
|
58
|
+
push:
|
|
59
|
+
branches:
|
|
60
|
+
- main
|
|
61
|
+
paths-ignore:
|
|
62
|
+
- '.mokogit/**'
|
|
63
|
+
- '.gitea/**'
|
|
64
|
+
- '.github/**'
|
|
65
|
+
- '.vscode/**'
|
|
66
|
+
- '.idea/**'
|
|
67
|
+
- 'docs/**'
|
|
68
|
+
- 'wiki/**'
|
|
69
|
+
- '**/*.md'
|
|
70
|
+
- '.editorconfig'
|
|
71
|
+
- '.gitignore'
|
|
72
|
+
- '.gitattributes'
|
|
73
|
+
- '.gitmodules'
|
|
74
|
+
- '.gitmessage'
|
|
75
|
+
- 'phpstan.neon'
|
|
76
|
+
- 'LICENSE'
|
|
77
|
+
# Daily safety-net: catch merges whose push event never created a run
|
|
42
78
|
# (e.g. this workflow file being re-synced from the template concurrently with the
|
|
43
79
|
# merge). Off-round minute to avoid a fleet-wide spike. The safety-net job below
|
|
44
80
|
# only dispatches a release when main actually has unreleased changes.
|
|
@@ -65,11 +101,27 @@ permissions:
|
|
|
65
101
|
contents: write
|
|
66
102
|
pull-requests: write
|
|
67
103
|
|
|
104
|
+
concurrency:
|
|
105
|
+
# Serialise the release path per COMMIT, not per ref: push / schedule /
|
|
106
|
+
# workflow_dispatch for the SAME main commit collapse into one group and
|
|
107
|
+
# de-dup as pending, so a fleet-wide burst does not stack N redundant
|
|
108
|
+
# publish pipelines for one release. Never cancel a publish already in
|
|
109
|
+
# progress (cancel-in-progress: false) -- cancelling mid-publish could leave
|
|
110
|
+
# a half-created release (npmjs published but Gitea-registry publish dropped).
|
|
111
|
+
group: auto-release-${{ github.event.head_commit.id || github.sha }}
|
|
112
|
+
cancel-in-progress: false
|
|
113
|
+
|
|
68
114
|
jobs:
|
|
69
115
|
# ── PR Opened → Rename branch to RC and build RC release ─────────────────────────
|
|
70
116
|
promote-rc:
|
|
71
117
|
name: Promote to RC
|
|
72
118
|
runs-on: release
|
|
119
|
+
# Own-repo writes: move rc + create release (contents:write), and dispatch
|
|
120
|
+
# deploy-rc (actions:write) — all via the per-repo github.token.
|
|
121
|
+
permissions:
|
|
122
|
+
contents: write
|
|
123
|
+
pull-requests: write
|
|
124
|
+
actions: write
|
|
73
125
|
# Skip on template repos (Template-*) — they scaffold other repos and do not release.
|
|
74
126
|
# Trigger-loop guard (#404 follow-up): NEVER run on bot/sync branches. A
|
|
75
127
|
# template-sync/provisioning push (e.g. chore/mokoonyx-template-sync-*) that opens or
|
|
@@ -85,11 +137,7 @@ jobs:
|
|
|
85
137
|
(github.event.action == 'opened' && github.event.pull_request.merged != true) ||
|
|
86
138
|
(github.event.action == 'synchronize' && github.event.pull_request.merged != true)
|
|
87
139
|
) &&
|
|
88
|
-
|
|
89
|
-
!startsWith(github.event.pull_request.head.ref, 'sync/') &&
|
|
90
|
-
!startsWith(github.event.pull_request.head.ref, 'bot/') &&
|
|
91
|
-
!startsWith(github.event.pull_request.head.ref, 'mokoonyx-template-sync') &&
|
|
92
|
-
!startsWith(github.event.pull_request.head.ref, 'template-sync') &&
|
|
140
|
+
github.event.pull_request.head.ref == 'dev' &&
|
|
93
141
|
!contains(github.event.pull_request.title, '[skip ci]') &&
|
|
94
142
|
!contains(github.event.pull_request.title, '[skip sync]')
|
|
95
143
|
) ||
|
|
@@ -100,7 +148,7 @@ jobs:
|
|
|
100
148
|
- name: Checkout repository
|
|
101
149
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
102
150
|
with:
|
|
103
|
-
token: ${{
|
|
151
|
+
token: ${{ github.token }}
|
|
104
152
|
fetch-depth: 1
|
|
105
153
|
submodules: recursive
|
|
106
154
|
|
|
@@ -111,25 +159,47 @@ jobs:
|
|
|
111
159
|
run: |
|
|
112
160
|
if [ -f /opt/mokocli/cli/version_bump.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then
|
|
113
161
|
echo Using pre-installed /opt/mokocli
|
|
162
|
+
# Keep the pre-installed copy current with mokocli main (auto-refresh; soft — never fails the run).
|
|
163
|
+
if git -C /opt/mokocli rev-parse --git-dir >/dev/null 2>&1; then
|
|
164
|
+
git -C /opt/mokocli pull --ff-only --quiet 2>/dev/null || echo " (mokocli git refresh skipped)"
|
|
165
|
+
REFRESH_TOK="$(printf '%s' "${MOKO_CLONE_TOKEN}" | tr -d '[:space:]')"
|
|
166
|
+
if [ -n "${REFRESH_TOK}" ] && command -v composer >/dev/null 2>&1; then
|
|
167
|
+
composer config -g http-basic.git.mokoconsulting.tech x-access-token "${REFRESH_TOK}" 2>/dev/null || true
|
|
168
|
+
( cd /opt/mokocli && composer install --no-dev --no-interaction --no-progress --optimize-autoloader --quiet ) 2>/dev/null || echo " (mokocli composer refresh skipped)"
|
|
169
|
+
fi
|
|
170
|
+
fi
|
|
114
171
|
echo MOKO_CLI=/opt/mokocli/cli >> $GITHUB_ENV
|
|
115
172
|
else
|
|
116
173
|
echo Falling back to fresh clone
|
|
117
174
|
if ! command -v composer > /dev/null 2>&1; then
|
|
118
175
|
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
|
|
119
176
|
fi
|
|
177
|
+
# Strip any stray whitespace/newline a pasted secret may carry, and mask
|
|
178
|
+
# it; the unquoted URL below otherwise word-splits on a trailing newline
|
|
179
|
+
# in MOKOGIT_TOKEN and git clone dies with "fatal: Too many arguments".
|
|
180
|
+
MOKO_CLONE_TOKEN="$(printf '%s' "${MOKO_CLONE_TOKEN}" | tr -d '[:space:]')"
|
|
181
|
+
echo "::add-mask::${MOKO_CLONE_TOKEN}"
|
|
182
|
+
if [ -z "${MOKO_CLONE_TOKEN}" ]; then
|
|
183
|
+
echo "::error::MOKOGIT_TOKEN secret is empty — cannot clone mokocli fallback." >&2
|
|
184
|
+
exit 1
|
|
185
|
+
fi
|
|
120
186
|
rm -rf /tmp/mokocli
|
|
121
|
-
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
|
|
122
|
-
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
|
|
187
|
+
CLONE_URL="https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git"
|
|
188
|
+
git clone --depth 1 --branch main --quiet "${CLONE_URL}" /tmp/mokocli
|
|
123
189
|
cd /tmp/mokocli
|
|
124
190
|
# Authenticate to the MokoGIT private Composer registry (git.mokoconsulting.tech)
|
|
125
191
|
# declared in mokocli composer.json (preferred-install=dist) before installing deps.
|
|
126
192
|
composer config -g http-basic.git.mokoconsulting.tech x-access-token "${MOKO_CLONE_TOKEN}"
|
|
193
|
+
export COMPOSER_AUTH="{\"http-basic\":{\"git.mokoconsulting.tech\":{\"username\":\"x-access-token\",\"password\":\"${MOKO_CLONE_TOKEN}\"}}}"
|
|
127
194
|
composer install --no-dev --no-interaction --no-progress --optimize-autoloader --quiet
|
|
128
195
|
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
|
|
129
196
|
fi
|
|
130
197
|
|
|
131
198
|
- name: Rename branch to rc
|
|
199
|
+
env:
|
|
200
|
+
MOKOGIT_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
|
132
201
|
run: |
|
|
202
|
+
PUSH_TOK="$(printf '%s' "$MOKOGIT_TOKEN" | tr -d '[:space:]')"; [ -z "$PUSH_TOK" ] && PUSH_TOK="${{ github.token }}"; echo "::add-mask::$PUSH_TOK"
|
|
133
203
|
API_BASE="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
|
|
134
204
|
AUTH="Authorization: token ${{ github.token }}"
|
|
135
205
|
FROM="${{ github.event.pull_request.head.ref || 'dev' }}"
|
|
@@ -145,7 +215,7 @@ jobs:
|
|
|
145
215
|
# returns HTTP 405 on ANY protected branch (force or not, even for a user in
|
|
146
216
|
# the force-push allowlist), so it cannot move a protected rc. git push honors
|
|
147
217
|
# the push + force-push allowlists and creates rc if it is absent.
|
|
148
|
-
PUSH_URL="https://x-access-token:${
|
|
218
|
+
PUSH_URL="https://x-access-token:${PUSH_TOK}@${MOKOGIT_URL#https://}/${GIT_ORG}/${GIT_REPO}.git"
|
|
149
219
|
git config --global user.name "mokogit-actions[bot]"
|
|
150
220
|
git config --global user.email "actions@mokoconsulting.tech"
|
|
151
221
|
git fetch --no-tags "$PUSH_URL" "${FROM}"
|
|
@@ -170,15 +240,23 @@ jobs:
|
|
|
170
240
|
- name: Trigger RC deploy
|
|
171
241
|
run: |
|
|
172
242
|
# Workflow-token pushes do NOT wake downstream workflows; dispatch deploy-rc explicitly.
|
|
173
|
-
curl -sf -X POST -H "Authorization: token ${{ github.token }}" \
|
|
243
|
+
curl -sf -X POST -H "Authorization: token ${{ github.token }}" \
|
|
244
|
+
-H "Content-Type: application/json" \
|
|
245
|
+
"${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}/actions/workflows/deploy-rc.yml/dispatches" \
|
|
246
|
+
-d '{"ref":"rc"}' \
|
|
247
|
+
&& echo "Dispatched deploy-rc on rc" \
|
|
248
|
+
|| echo "::warning::deploy-rc dispatch failed (no deploy-rc.yml on rc? non-go platform)"
|
|
174
249
|
|
|
175
250
|
- name: Checkout rc and configure git
|
|
251
|
+
env:
|
|
252
|
+
MOKOGIT_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
|
176
253
|
run: |
|
|
254
|
+
PUSH_TOK="$(printf '%s' "$MOKOGIT_TOKEN" | tr -d '[:space:]')"; [ -z "$PUSH_TOK" ] && PUSH_TOK="${{ github.token }}"; echo "::add-mask::$PUSH_TOK"
|
|
177
255
|
git fetch origin rc
|
|
178
256
|
git checkout rc
|
|
179
257
|
git config --local user.email "mokogit-actions[bot]@mokoconsulting.tech"
|
|
180
258
|
git config --local user.name "mokogit-actions[bot]"
|
|
181
|
-
git remote set-url origin "https://x-access-token:${
|
|
259
|
+
git remote set-url origin "https://x-access-token:${PUSH_TOK}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
|
182
260
|
|
|
183
261
|
- name: Publish RC release
|
|
184
262
|
continue-on-error: true
|
|
@@ -236,19 +314,28 @@ jobs:
|
|
|
236
314
|
name: Build & Release Pipeline
|
|
237
315
|
runs-on: release
|
|
238
316
|
# Skip on template repos (Template-*) — they scaffold other repos and do not release.
|
|
239
|
-
#
|
|
240
|
-
#
|
|
241
|
-
#
|
|
317
|
+
# Stable release fires on a merged PR into main (pull_request:closed + merged) OR a
|
|
318
|
+
# direct PUSH to main. The pull_request path is the reliable one — a PR-merge does not
|
|
319
|
+
# always emit a base-branch push event to Actions, so relying on push alone silently
|
|
320
|
+
# skipped releases (the scheduled-safety-net below was the band-aid). The release
|
|
321
|
+
# steps already read github.event.pull_request.head.ref, so they handle both events.
|
|
322
|
+
# Loop guard: skip a self-push that carries
|
|
323
|
+
# [skip ci]/[skip sync] (mokocli's build commit + the changelog-promote commit); the
|
|
324
|
+
# non-code paths-ignore on the push trigger already drops docs/CI-only pushes.
|
|
325
|
+
# workflow_dispatch stays exempt (explicit human run).
|
|
242
326
|
if: >-
|
|
243
327
|
!startsWith(github.event.repository.name, 'Template-') &&
|
|
244
328
|
(
|
|
245
329
|
(
|
|
330
|
+
github.event_name == 'push' &&
|
|
331
|
+
!contains(github.event.head_commit.message, '[skip ci]') &&
|
|
332
|
+
!contains(github.event.head_commit.message, '[skip sync]')
|
|
333
|
+
) ||
|
|
334
|
+
(
|
|
335
|
+
github.event_name == 'pull_request' &&
|
|
336
|
+
github.event.action == 'closed' &&
|
|
246
337
|
github.event.pull_request.merged == true &&
|
|
247
|
-
|
|
248
|
-
!startsWith(github.event.pull_request.head.ref, 'sync/') &&
|
|
249
|
-
!startsWith(github.event.pull_request.head.ref, 'bot/') &&
|
|
250
|
-
!startsWith(github.event.pull_request.head.ref, 'mokoonyx-template-sync') &&
|
|
251
|
-
!startsWith(github.event.pull_request.head.ref, 'template-sync') &&
|
|
338
|
+
github.event.pull_request.base.ref == 'main' &&
|
|
252
339
|
!contains(github.event.pull_request.title, '[skip ci]') &&
|
|
253
340
|
!contains(github.event.pull_request.title, '[skip sync]')
|
|
254
341
|
) ||
|
|
@@ -259,15 +346,18 @@ jobs:
|
|
|
259
346
|
- name: Checkout repository
|
|
260
347
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
261
348
|
with:
|
|
262
|
-
token: ${{
|
|
349
|
+
token: ${{ github.token }}
|
|
263
350
|
fetch-depth: 0
|
|
264
351
|
submodules: recursive
|
|
265
352
|
|
|
266
353
|
- name: Configure git for bot pushes
|
|
354
|
+
env:
|
|
355
|
+
MOKOGIT_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
|
267
356
|
run: |
|
|
357
|
+
PUSH_TOK="$(printf '%s' "$MOKOGIT_TOKEN" | tr -d '[:space:]')"; [ -z "$PUSH_TOK" ] && PUSH_TOK="${{ github.token }}"; echo "::add-mask::$PUSH_TOK"
|
|
268
358
|
git config --local user.email "mokogit-actions[bot]@mokoconsulting.tech"
|
|
269
359
|
git config --local user.name "mokogit-actions[bot]"
|
|
270
|
-
git remote set-url origin "https://x-access-token:${
|
|
360
|
+
git remote set-url origin "https://x-access-token:${PUSH_TOK}@git.mokoconsulting.tech/${{ github.repository }}.git"
|
|
271
361
|
|
|
272
362
|
- name: Check for merge conflict markers
|
|
273
363
|
run: |
|
|
@@ -286,7 +376,6 @@ jobs:
|
|
|
286
376
|
env:
|
|
287
377
|
MOKO_CLONE_TOKEN: ${{ secrets.MOKOGIT_TOKEN }}
|
|
288
378
|
MOKO_CLONE_HOST: git.mokoconsulting.tech/MokoConsulting
|
|
289
|
-
COMPOSER_AUTH: '{"github-oauth":{"github.com":"${{ secrets.GH_MIRROR_TOKEN }}"}}'
|
|
290
379
|
run: |
|
|
291
380
|
if [ -f /opt/mokocli/cli/version_bump.php ] && [ -f /opt/mokocli/vendor/autoload.php ]; then
|
|
292
381
|
echo Using pre-installed /opt/mokocli
|
|
@@ -296,13 +385,23 @@ jobs:
|
|
|
296
385
|
if ! command -v composer > /dev/null 2>&1; then
|
|
297
386
|
sudo apt-get update -qq && sudo apt-get install -y -qq php-cli php-mbstring php-xml php-zip php-curl composer > /dev/null 2>&1
|
|
298
387
|
fi
|
|
388
|
+
# Strip any stray whitespace/newline a pasted secret may carry, and mask
|
|
389
|
+
# it; the unquoted URL below otherwise word-splits on a trailing newline
|
|
390
|
+
# in MOKOGIT_TOKEN and git clone dies with "fatal: Too many arguments".
|
|
391
|
+
MOKO_CLONE_TOKEN="$(printf '%s' "${MOKO_CLONE_TOKEN}" | tr -d '[:space:]')"
|
|
392
|
+
echo "::add-mask::${MOKO_CLONE_TOKEN}"
|
|
393
|
+
if [ -z "${MOKO_CLONE_TOKEN}" ]; then
|
|
394
|
+
echo "::error::MOKOGIT_TOKEN secret is empty — cannot clone mokocli fallback." >&2
|
|
395
|
+
exit 1
|
|
396
|
+
fi
|
|
299
397
|
rm -rf /tmp/mokocli
|
|
300
|
-
CLONE_URL=https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git
|
|
301
|
-
git clone --depth 1 --branch main --quiet $CLONE_URL /tmp/mokocli
|
|
398
|
+
CLONE_URL="https://x-access-token:${MOKO_CLONE_TOKEN}@${MOKO_CLONE_HOST}/mokocli.git"
|
|
399
|
+
git clone --depth 1 --branch main --quiet "${CLONE_URL}" /tmp/mokocli
|
|
302
400
|
cd /tmp/mokocli
|
|
303
401
|
# Authenticate to the MokoGIT private Composer registry (git.mokoconsulting.tech)
|
|
304
402
|
# declared in mokocli composer.json (preferred-install=dist) before installing deps.
|
|
305
403
|
composer config -g http-basic.git.mokoconsulting.tech x-access-token "${MOKO_CLONE_TOKEN}"
|
|
404
|
+
export COMPOSER_AUTH="{\"http-basic\":{\"git.mokoconsulting.tech\":{\"username\":\"x-access-token\",\"password\":\"${MOKO_CLONE_TOKEN}\"}}}"
|
|
306
405
|
composer install --no-dev --no-interaction --no-progress --optimize-autoloader --quiet
|
|
307
406
|
echo MOKO_CLI=/tmp/mokocli/cli >> $GITHUB_ENV
|
|
308
407
|
fi
|
|
@@ -310,7 +409,14 @@ jobs:
|
|
|
310
409
|
- name: "Detect platform"
|
|
311
410
|
id: platform
|
|
312
411
|
run: |
|
|
313
|
-
|
|
412
|
+
# Detect the platform from the repo's NATIVE manifest and emit it to
|
|
413
|
+
# $GITHUB_OUTPUT for downstream steps. READ-ONLY: the former metadata
|
|
414
|
+
# write-back (platform_detect.php --update --token --owner --repo) has
|
|
415
|
+
# been REMOVED — platform is now derived from the native manifest by the
|
|
416
|
+
# MokoCLI build agent, so this workflow no longer writes to the metadata
|
|
417
|
+
# registry. Non-fatal (|| true) so a detection hiccup never blocks a release.
|
|
418
|
+
php ${MOKO_CLI}/platform_detect.php --path . --github-output \
|
|
419
|
+
2>/dev/null || true
|
|
314
420
|
php ${MOKO_CLI}/manifest_read.php --path . --github-output 2>/dev/null || true
|
|
315
421
|
|
|
316
422
|
- name: "Determine version bump level"
|
|
@@ -437,45 +543,22 @@ jobs:
|
|
|
437
543
|
if [ -n "$VERSION" ] && [ -f "CHANGELOG.md" ]; then
|
|
438
544
|
php ${MOKO_CLI}/changelog_promote.php --path . --version "$VERSION"
|
|
439
545
|
git add CHANGELOG.md
|
|
440
|
-
git commit -m "chore: promote changelog [Unreleased] → [${VERSION}]" || true
|
|
546
|
+
git commit -m "chore: promote changelog [Unreleased] → [${VERSION}] [skip ci]" || true
|
|
441
547
|
git push origin main || true
|
|
442
548
|
echo "Changelog promoted: [Unreleased] → [${VERSION}]"
|
|
443
549
|
fi
|
|
444
550
|
|
|
445
|
-
|
|
446
|
-
- name: "Step 9: Mirror release to GitHub"
|
|
447
|
-
if: >-
|
|
448
|
-
steps.version.outputs.skip != 'true' &&
|
|
449
|
-
secrets.GH_MIRROR_TOKEN != ''
|
|
450
|
-
continue-on-error: true
|
|
551
|
+
- name: Dispatch npm publish (bump has persisted to main)
|
|
451
552
|
run: |
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
echo "GitHub mirror updated" >> $GITHUB_STEP_SUMMARY
|
|
462
|
-
|
|
463
|
-
# -- STEP 10: Sync main branch to GitHub mirror ----------------------------
|
|
464
|
-
- name: "Step 10: Push main to GitHub mirror"
|
|
465
|
-
if: >-
|
|
466
|
-
steps.version.outputs.skip != 'true' &&
|
|
467
|
-
secrets.GH_MIRROR_TOKEN != ''
|
|
468
|
-
continue-on-error: true
|
|
469
|
-
run: |
|
|
470
|
-
GH_REPO="${{ vars.GH_MIRROR_REPO || github.repository }}"
|
|
471
|
-
GH_ORG=$(echo "$GH_REPO" | cut -d/ -f1)
|
|
472
|
-
GH_NAME=$(echo "$GH_REPO" | cut -d/ -f2)
|
|
473
|
-
git remote add github "https://x-access-token:${{ secrets.GH_MIRROR_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git" 2>/dev/null || \
|
|
474
|
-
git remote set-url github "https://x-access-token:${{ secrets.GH_MIRROR_TOKEN }}@github.com/${GH_ORG}/${GH_NAME}.git"
|
|
475
|
-
git fetch origin main --depth=1
|
|
476
|
-
git push github origin/main:refs/heads/main --force 2>/dev/null \
|
|
477
|
-
&& echo "main branch pushed to GitHub mirror" \
|
|
478
|
-
|| echo "WARNING: GitHub mirror push failed"
|
|
553
|
+
curl -sf -X POST -H "Authorization: token ${{ github.token }}" \
|
|
554
|
+
-H "Content-Type: application/json" \
|
|
555
|
+
"${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}/actions/workflows/npm-publish.yml/dispatches" \
|
|
556
|
+
-d '{"ref":"main"}' \
|
|
557
|
+
&& echo "Dispatched npm-publish on main" \
|
|
558
|
+
|| echo "::warning::npm-publish dispatch failed (no npm-publish.yml on this repo? non-npm platform)"
|
|
559
|
+
|
|
560
|
+
# GitHub mirroring (release assets + main branch) moved to an out-of-band
|
|
561
|
+
# OAuth push-mirror (Gitea repo setting) — former Steps 9 & 10 removed.
|
|
479
562
|
|
|
480
563
|
- name: "Step 11: Delete rc branch (dev reset moved to cascade-dev.yml)"
|
|
481
564
|
if: steps.version.outputs.skip != 'true'
|
|
@@ -519,9 +602,13 @@ jobs:
|
|
|
519
602
|
continue-on-error: true
|
|
520
603
|
run: |
|
|
521
604
|
API_BASE="${MOKOGIT_URL}/api/v1/repos/${GIT_ORG}/${GIT_REPO}"
|
|
605
|
+
# No `|| true`: let a failed dev-version advance surface as a red step.
|
|
606
|
+
# `continue-on-error: true` above still keeps the release itself green,
|
|
607
|
+
# but a swallowed exit code is what let this go unnoticed for months
|
|
608
|
+
# (dev silently drifting below stable → dev-channel updates vanish).
|
|
522
609
|
php ${MOKO_CLI}/version_reset_dev.php \
|
|
523
610
|
--token "${{ github.token }}" --api-base "${API_BASE}" \
|
|
524
|
-
--branch dev --path . 2>&1
|
|
611
|
+
--branch dev --path . 2>&1
|
|
525
612
|
|
|
526
613
|
# -- Summary --------------------------------------------------------------
|
|
527
614
|
- name: Pipeline Summary
|
|
@@ -559,8 +646,10 @@ jobs:
|
|
|
559
646
|
name: Scheduled release safety-net
|
|
560
647
|
runs-on: ubuntu-latest
|
|
561
648
|
if: github.event_name == 'schedule' && !startsWith(github.event.repository.name, 'Template-')
|
|
649
|
+
# Own-repo write: dispatch a release when main has unreleased changes.
|
|
562
650
|
permissions:
|
|
563
651
|
contents: read
|
|
652
|
+
actions: write
|
|
564
653
|
steps:
|
|
565
654
|
- name: Checkout main
|
|
566
655
|
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
|
|
@@ -571,6 +660,8 @@ jobs:
|
|
|
571
660
|
- name: Dispatch release if main has unreleased changes
|
|
572
661
|
env:
|
|
573
662
|
MOKOGIT_TOKEN: ${{ github.token }}
|
|
663
|
+
NTFY_URL: ${{ vars.NTFY_URL }}
|
|
664
|
+
NTFY_TOPIC: ${{ vars.NTFY_TOPIC }}
|
|
574
665
|
run: |
|
|
575
666
|
# [Unreleased] is non-empty precisely when changes were merged but not yet
|
|
576
667
|
# released (the release job promotes it to a version and empties it).
|
|
@@ -583,14 +674,36 @@ jobs:
|
|
|
583
674
|
exit 0
|
|
584
675
|
fi
|
|
585
676
|
echo "Unreleased changes detected on main — a merge release was likely missed."
|
|
586
|
-
|
|
677
|
+
API="${MOKOGIT_URL}/api/v1/repos/${{ github.repository }}"
|
|
678
|
+
# Snapshot the newest run id BEFORE dispatching. Gitea can return 2xx to
|
|
679
|
+
# workflow_dispatch WITHOUT creating a run (see mokocli#499), so an HTTP
|
|
680
|
+
# 204 is NOT proof of recovery — confirm a new run actually appears.
|
|
681
|
+
before=$(curl -s -H "Authorization: token ${MOKOGIT_TOKEN}" "${API}/actions/tasks?limit=1" \
|
|
682
|
+
| python3 -c "import sys,json;r=json.load(sys.stdin).get('workflow_runs',[]);print(r[0]['id'] if r else 0)" 2>/dev/null || echo 0)
|
|
683
|
+
echo "Dispatching a release via the safety-net (newest run before = ${before})."
|
|
587
684
|
HTTP=$(curl -s -o /dev/null -w '%{http_code}' -X POST \
|
|
588
685
|
-H "Authorization: token ${MOKOGIT_TOKEN}" \
|
|
589
686
|
-H "Content-Type: application/json" \
|
|
590
687
|
-d '{"ref":"main","inputs":{"action":"release"}}' \
|
|
591
|
-
"${
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
688
|
+
"${API}/actions/workflows/auto-release.yml/dispatches")
|
|
689
|
+
echo "Dispatch HTTP ${HTTP}."
|
|
690
|
+
# Verify a NEW run actually materialised (a 2xx alone is not proof).
|
|
691
|
+
created=0
|
|
692
|
+
for i in $(seq 1 12); do
|
|
693
|
+
sleep 10
|
|
694
|
+
newest=$(curl -s -H "Authorization: token ${MOKOGIT_TOKEN}" "${API}/actions/tasks?limit=8" \
|
|
695
|
+
| python3 -c "import sys,json;rs=json.load(sys.stdin).get('workflow_runs',[]);print(max([r['id'] for r in rs] or [0]))" 2>/dev/null || echo 0)
|
|
696
|
+
if [ "${newest:-0}" -gt "${before:-0}" ]; then created=1; break; fi
|
|
697
|
+
done
|
|
698
|
+
if [ "$created" = "1" ]; then
|
|
699
|
+
echo "Release run created — safety-net recovery succeeded."
|
|
700
|
+
exit 0
|
|
701
|
+
fi
|
|
702
|
+
# No run materialised: turn the silent no-op into a LOUD, actionable failure.
|
|
703
|
+
echo "::error::Safety-net dispatched a release (HTTP ${HTTP}) but NO run was created — Gitea workflow_dispatch no-run (mokocli#499). main has UNRELEASED changes that did not publish. Recover by merging a change to main or running auto-release from the web UI."
|
|
704
|
+
if [ -n "${NTFY_URL:-}" ] && [ -n "${NTFY_TOPIC:-}" ]; then
|
|
705
|
+
curl -s -X POST -H "Title: Release recovery FAILED" -H "Priority: high" \
|
|
706
|
+
-d "Safety-net could not recover a missed release on ${{ github.repository }}: workflow_dispatch created no run (mokocli#499). Trigger a release manually." \
|
|
707
|
+
"${NTFY_URL%/}/${NTFY_TOPIC}" >/dev/null 2>&1 || true
|
|
596
708
|
fi
|
|
709
|
+
exit 1
|