@mutmutco/pi-plugin 4.5.130 → 4.5.132

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mutmutco/pi-plugin",
3
- "version": "4.5.130",
3
+ "version": "4.5.132",
4
4
  "description": "MMI workflow skills and org gates delivery.",
5
5
  "author": {
6
6
  "name": "MMI Future",
@@ -50,6 +50,7 @@ concurrency:
50
50
  cancel-in-progress: true
51
51
 
52
52
  permissions:
53
+ actions: read # #8206: exact-SHA development workflow verdict
53
54
  contents: read
54
55
  # MMI-Hub#7542: the product image build below reads org private packages with the workflow's
55
56
  # own ephemeral token (NODE_AUTH_TOKEN) — the same reader the central deploy uses.
@@ -65,12 +66,40 @@ jobs:
65
66
  defaults:
66
67
  run: { working-directory: {{GATE_WORKDIR}} }{{GATE_SERVICES_YAML}}
67
68
  steps:
68
- - uses: mutmutco/MMI-Hub/.github/actions/runner-checkout@{{GATE_RUNNER_SHA}}
69
+ # #8206: keep a fresh successful tag gate; promote the exact development verdict, not a ref.
70
+ - name: Reuse development gate for rc tag
71
+ id: development-gate
72
+ uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
73
+ with:
74
+ script: |
75
+ core.setOutput('reuse', 'false');
76
+ if (context.eventName !== 'push' || !/^refs\/tags\/v.+-rc\.\d+$/.test(context.ref) || !/^[0-9a-f]{40}$/.test(context.sha)) return;
77
+ try {
78
+ const { data: current } = await github.rest.actions.getWorkflowRun({ ...context.repo, run_id: context.runId });
79
+ const { data } = await github.rest.actions.listWorkflowRuns({
80
+ ...context.repo, workflow_id: current.workflow_id, branch: 'development',
81
+ event: 'push', head_sha: context.sha, per_page: 100
82
+ });
83
+ // API returns newest first: a newer red/pending rerun must not reuse an older green.
84
+ const run = data.workflow_runs[0];
85
+ if (!run || run.head_sha !== context.sha || run.head_branch !== 'development' ||
86
+ run.event !== 'push' || run.status !== 'completed' || run.conclusion !== 'success') return;
87
+ const jobs = await github.paginate(github.rest.actions.listJobsForWorkflowRun, {
88
+ ...context.repo, run_id: run.id, filter: 'latest', per_page: 100
89
+ });
90
+ if (!jobs.some(job => job.name === 'gate' && job.status === 'completed' && job.conclusion === 'success')) return;
91
+ core.setOutput('reuse', 'true');
92
+ core.info('Reusing successful development gate run ' + run.id + ' for exact SHA ' + context.sha);
93
+ } catch (error) {
94
+ core.warning('Development gate proof unavailable; running normal gate: ' + error.message);
95
+ }
96
+ - if: ${{ steps.development-gate.outputs.reuse != 'true' }}
97
+ uses: mutmutco/MMI-Hub/.github/actions/runner-checkout@{{GATE_RUNNER_SHA}}
69
98
  with:
70
99
  lockfile-path: {{GATE_CACHE_DEP_PATH}}
71
100
  fetch-depth: 0 # #8129: runbook freshness needs the PR merge-base history.
72
101
  - name: Runbook guard
73
- if: ${{ github.event_name == 'pull_request' }}
102
+ if: ${{ steps.development-gate.outputs.reuse != 'true' && (github.event_name == 'pull_request') }}
74
103
  uses: mutmutco/MMI-Hub/.github/actions/runbook-guard@{{GATE_RUNBOOK_SHA}}
75
104
  with:
76
105
  base-ref: origin/${{ github.base_ref }}
@@ -81,11 +110,13 @@ jobs:
81
110
  # `npm config get cache` for any explicit cache restore). Job-level `env:` cannot use the
82
111
  # `runner` context — write via GITHUB_ENV from the shell `$RUNNER_TEMP` instead.
83
112
  - name: Isolate npm cache (per-job)
113
+ if: ${{ steps.development-gate.outputs.reuse != 'true' }}
84
114
  shell: bash
85
115
  run: echo "NPM_CONFIG_CACHE=$RUNNER_TEMP/npm-cache" >> "$GITHUB_ENV"
86
116
  # MMI-Hub#5111: Windows CRLF in tracked shell scripts breaks Linux runners before the real
87
117
  # check can explain it. Inspect only tracked files before install; .gitattributes is the fix.
88
118
  - name: Line-ending guard
119
+ if: ${{ steps.development-gate.outputs.reuse != 'true' }}
89
120
  shell: bash
90
121
  run: |
91
122
  offenders=$(mktemp)
@@ -116,6 +147,7 @@ jobs:
116
147
  # files (Dockerfile + docker-compose.yml) skip in a second — no new job, no new required
117
148
  # context, no ruleset or registry change (#7012 needs nothing to cover).
118
149
  - name: Product image build (tenant-container only)
150
+ if: ${{ steps.development-gate.outputs.reuse != 'true' }}
119
151
  env:
120
152
  # The documented build-secret opt-in (compose `build.secrets` + registry
121
153
  # requiredBuildSecrets `NODE_AUTH_TOKEN=@github-packages-token`): the workflow's own
@@ -146,25 +178,27 @@ jobs:
146
178
  # MMI-Hub#5871: declare the npm MAJOR rather than inheriting whatever the runner's node bundles.
147
179
  # A bare major, never an exact patch (it goes stale and then prescribes downgrading operator
148
180
  # hosts toward it, #5862) and never `latest` (it takes the next major silently, #4782).
149
- - if: ${{ '{{GATE_RUNTIME}}' == 'node' }}
181
+ - if: ${{ steps.development-gate.outputs.reuse != 'true' && ('{{GATE_RUNTIME}}' == 'node') }}
150
182
  uses: mutmutco/MMI-Hub/.github/actions/runner-node-toolchain@{{GATE_RUNNER_SHA}}
151
183
  with:
152
184
  node-version: 24
153
185
  npm-version: '12'
154
- - if: ${{ '{{GATE_RUNTIME}}' == 'python' }}
186
+ - if: ${{ steps.development-gate.outputs.reuse != 'true' && ('{{GATE_RUNTIME}}' == 'python') }}
155
187
  uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
156
188
  with: { python-version: '{{GATE_PY_VERSION}}' }
157
189
  # MMI-Hub#3446: assert the runtime toolchain is on PATH BEFORE the install step. Node uses the
158
190
  # runner-node-toolchain composite above (setup-node + preflight in one action, #5610). Python
159
191
  # keeps the inline preflight below.
160
192
  - name: Toolchain preflight
161
- if: ${{ '{{GATE_RUNTIME}}' == 'python' }}
193
+ if: ${{ steps.development-gate.outputs.reuse != 'true' && ('{{GATE_RUNTIME}}' == 'python') }}
162
194
  run: |
163
195
  python3 --version || { echo "::error title=CI runner toolchain::RUNNER NOT PROVISIONED — python3 not on PATH after setup-python. This is the runner, not your diff; no install or test ran. Re-run the job; if it persists the mmi-runner python toolchain needs attention (docs/Guides/gh-runner-runbook.md in MMI-Hub)."; exit 1; }
164
196
  - run: {{GATE_INSTALL_CMD}}
197
+ if: ${{ steps.development-gate.outputs.reuse != 'true' }}
165
198
  # #3178: the check runs under the org wall-clock budget — a hung suite dies at the ceiling instead
166
199
  # of squatting a runner lane for GitHub's 6h default. ci-audit + the release train enforce this step.
167
200
  - uses: mutmutco/MMI-Hub/.github/actions/run-with-budget@{{GATE_BUDGET_SHA}}
201
+ if: ${{ steps.development-gate.outputs.reuse != 'true' }}
168
202
  with:
169
203
  command: {{GATE_CMD}}
170
204
  max-seconds: {{GATE_MAX_SECONDS}}
@@ -8,6 +8,7 @@ concurrency:
8
8
  group: gate-${{ github.event.pull_request.number || github.ref }}
9
9
  cancel-in-progress: true
10
10
  permissions:
11
+ actions: read # #8206: exact-SHA development workflow verdict
11
12
  contents: read
12
13
  packages: read
13
14
  jobs:
@@ -15,26 +16,59 @@ jobs:
15
16
  runs-on: [self-hosted, linux, x64, mmi-live]
16
17
  timeout-minutes: 10
17
18
  steps:
18
- - uses: mutmutco/MMI-Hub/.github/actions/runner-checkout@{{GATE_RUNNER_SHA}}
19
+ # #8206: keep a fresh successful tag gate; promote the exact development verdict, not a ref.
20
+ - name: Reuse development gate for rc tag
21
+ id: development-gate
22
+ uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
23
+ with:
24
+ script: |
25
+ core.setOutput('reuse', 'false');
26
+ if (context.eventName !== 'push' || !/^refs\/tags\/v.+-rc\.\d+$/.test(context.ref) || !/^[0-9a-f]{40}$/.test(context.sha)) return;
27
+ try {
28
+ const { data: current } = await github.rest.actions.getWorkflowRun({ ...context.repo, run_id: context.runId });
29
+ const { data } = await github.rest.actions.listWorkflowRuns({
30
+ ...context.repo, workflow_id: current.workflow_id, branch: 'development',
31
+ event: 'push', head_sha: context.sha, per_page: 100
32
+ });
33
+ // API returns newest first: a newer red/pending rerun must not reuse an older green.
34
+ const run = data.workflow_runs[0];
35
+ if (!run || run.head_sha !== context.sha || run.head_branch !== 'development' ||
36
+ run.event !== 'push' || run.status !== 'completed' || run.conclusion !== 'success') return;
37
+ const jobs = await github.paginate(github.rest.actions.listJobsForWorkflowRun, {
38
+ ...context.repo, run_id: run.id, filter: 'latest', per_page: 100
39
+ });
40
+ if (!jobs.some(job => job.name === 'gate' && job.status === 'completed' && job.conclusion === 'success')) return;
41
+ core.setOutput('reuse', 'true');
42
+ core.info('Reusing successful development gate run ' + run.id + ' for exact SHA ' + context.sha);
43
+ } catch (error) {
44
+ core.warning('Development gate proof unavailable; running normal gate: ' + error.message);
45
+ }
46
+ - if: ${{ steps.development-gate.outputs.reuse != 'true' }}
47
+ uses: mutmutco/MMI-Hub/.github/actions/runner-checkout@{{GATE_RUNNER_SHA}}
19
48
  with:
20
49
  lockfile-path: package-lock.json
21
50
  fetch-depth: 0 # #8129: runbook freshness needs the PR merge-base history.
22
51
  - name: Runbook guard
23
- if: ${{ github.event_name == 'pull_request' }}
52
+ if: ${{ steps.development-gate.outputs.reuse != 'true' && (github.event_name == 'pull_request') }}
24
53
  uses: mutmutco/MMI-Hub/.github/actions/runbook-guard@{{GATE_RUNBOOK_SHA}}
25
54
  with:
26
55
  base-ref: origin/${{ github.base_ref }}
27
56
  - name: Isolate npm cache
57
+ if: ${{ steps.development-gate.outputs.reuse != 'true' }}
28
58
  run: echo "NPM_CONFIG_CACHE=$RUNNER_TEMP/npm-cache" >> "$GITHUB_ENV"
29
59
  - uses: mutmutco/MMI-Hub/.github/actions/runner-node-toolchain@{{GATE_RUNNER_SHA}}
60
+ if: ${{ steps.development-gate.outputs.reuse != 'true' }}
30
61
  with:
31
62
  node-version: 24
32
63
  npm-version: '12'
33
64
  - run: npm ci --no-audit --no-fund
65
+ if: ${{ steps.development-gate.outputs.reuse != 'true' }}
34
66
  - run: npm ci --prefix module --no-audit --no-fund
67
+ if: ${{ steps.development-gate.outputs.reuse != 'true' }}
35
68
  env:
36
69
  NODE_AUTH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37
70
  - uses: mutmutco/MMI-Hub/.github/actions/run-with-budget@{{GATE_BUDGET_SHA}}
71
+ if: ${{ steps.development-gate.outputs.reuse != 'true' }}
38
72
  with:
39
73
  command: npm run typecheck && npm run build && npm --prefix module run check
40
74
  max-seconds: {{GATE_MAX_SECONDS}}