@metasession.co/devaudit-cli 0.3.13 → 0.3.14

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.
@@ -117,19 +117,47 @@ jobs:
117
117
  echo "In-scope releases to promote: ${REQS}"
118
118
  echo "REQS=${REQS}" >> "$GITHUB_ENV"
119
119
 
120
+ - name: Start production deployment cycles
121
+ run: |
122
+ chmod +x scripts/report-test-cycle.sh 2>/dev/null || true
123
+ for PREFIX in ${REQS}; do
124
+ RESP=$(curl -fsS -H "Authorization: Bearer ${DEVAUDIT_API_KEY}" \
125
+ "${BASE}/api/ci/releases/resolve?projectSlug=${PROJECT_SLUG}&versionPrefix=${PREFIX}")
126
+ VERSION=$(echo "$RESP" | jq -r '.latest.version // empty')
127
+ [ -n "$VERSION" ] || VERSION="$PREFIX"
128
+ bash scripts/report-test-cycle.sh start \
129
+ --project-slug "$PROJECT_SLUG" --release "$VERSION" \
130
+ --sdlc-stage 5 --environment production --cycle-kind deployment \
131
+ --provider github_actions --external-run-id "$CI_RUN" \
132
+ --external-run-attempt "${{ github.run_attempt }}" --external-job-id "host-deployment" \
133
+ --idempotency-key "github:${{ github.repository }}:post-deploy-prod.deployment:${CI_RUN}:${{ github.run_attempt }}:5:${VERSION}" \
134
+ --commit-sha "$GIT_SHA" --branch main \
135
+ --workflow-name "Post-Deploy Production" \
136
+ --workflow-url "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
137
+ done
138
+
120
139
  - name: Wait for production deployment
140
+ id: wait_deployment
121
141
  run: |
142
+ DEPLOY_READY=false
122
143
  for i in $(seq 1 30); do
123
144
  HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "${PROD_URL}/" || echo "000")
124
145
  if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 400 ]; then
125
146
  echo "Production is up (HTTP ${HTTP_CODE})"
147
+ DEPLOY_READY=true
126
148
  break
127
149
  fi
128
150
  echo "Attempt ${i}/30: HTTP ${HTTP_CODE} — waiting 10s..."
129
151
  sleep 10
130
152
  done
153
+ if [ "$DEPLOY_READY" != "true" ]; then
154
+ echo "::error::Production did not become ready within the deployment window"
155
+ exit 1
156
+ fi
131
157
 
132
158
  - name: Confirm terminal host deployment success
159
+ id: host_deployment
160
+ if: steps.wait_deployment.outcome == 'success'
133
161
  env:
134
162
  GH_TOKEN: ${{ github.token }}
135
163
  run: |
@@ -140,7 +168,68 @@ jobs:
140
168
  --max-attempts=30 \
141
169
  --poll-seconds=10
142
170
 
171
+ - name: Complete production deployment cycles
172
+ if: always() && env.BASE != ''
173
+ run: |
174
+ if [ "${{ steps.wait_deployment.outcome }}" = "success" ] && [ "${{ steps.host_deployment.outcome }}" = "success" ]; then
175
+ OUTCOME=passed
176
+ CHECK_STATUS=successful
177
+ elif [ "${{ steps.wait_deployment.outcome }}" = "cancelled" ] || [ "${{ steps.host_deployment.outcome }}" = "cancelled" ]; then
178
+ OUTCOME=cancelled
179
+ CHECK_STATUS=cancelled
180
+ else
181
+ OUTCOME=failed
182
+ CHECK_STATUS=failed
183
+ fi
184
+ chmod +x scripts/report-test-cycle.sh scripts/report-release-check.sh 2>/dev/null || true
185
+ for PREFIX in ${REQS}; do
186
+ RESP=$(curl -fsS -H "Authorization: Bearer ${DEVAUDIT_API_KEY}" \
187
+ "${BASE}/api/ci/releases/resolve?projectSlug=${PROJECT_SLUG}&versionPrefix=${PREFIX}")
188
+ VERSION=$(echo "$RESP" | jq -r '.latest.version // empty')
189
+ [ -n "$VERSION" ] || VERSION="$PREFIX"
190
+ bash scripts/report-test-cycle.sh complete \
191
+ --project-slug "$PROJECT_SLUG" --release "$VERSION" \
192
+ --sdlc-stage 5 --environment production --cycle-kind deployment \
193
+ --provider github_actions --external-run-id "$CI_RUN" \
194
+ --external-run-attempt "${{ github.run_attempt }}" --external-job-id "host-deployment" \
195
+ --idempotency-key "github:${{ github.repository }}:post-deploy-prod.deployment:${CI_RUN}:${{ github.run_attempt }}:5:${VERSION}" \
196
+ --commit-sha "$GIT_SHA" --branch main \
197
+ --workflow-name "Post-Deploy Production" \
198
+ --workflow-url "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
199
+ --outcome "$OUTCOME" --outcome-reason "host deployment: ${{ steps.host_deployment.outcome }}"
200
+ bash scripts/report-release-check.sh \
201
+ --project-slug "$PROJECT_SLUG" --release "$VERSION" \
202
+ --check-key "production-deployment:${CI_RUN}:${{ github.run_attempt }}" \
203
+ --label "Production Deployment" --provider github_actions --status "$CHECK_STATUS" \
204
+ --external-run-id "$CI_RUN" \
205
+ --external-url "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
206
+ --commit-sha "$GIT_SHA" --branch main \
207
+ --details-json '{"waitOutcome":"${{ steps.wait_deployment.outcome }}","hostOutcome":"${{ steps.host_deployment.outcome }}"}'
208
+ done
209
+
210
+ - name: Start production smoke cycles
211
+ if: steps.wait_deployment.outcome == 'success' && steps.host_deployment.outcome == 'success'
212
+ run: |
213
+ chmod +x scripts/report-test-cycle.sh 2>/dev/null || true
214
+ for PREFIX in ${REQS}; do
215
+ RESP=$(curl -fsS -H "Authorization: Bearer ${DEVAUDIT_API_KEY}" \
216
+ "${BASE}/api/ci/releases/resolve?projectSlug=${PROJECT_SLUG}&versionPrefix=${PREFIX}")
217
+ VERSION=$(echo "$RESP" | jq -r '.latest.version // empty')
218
+ [ -n "$VERSION" ] || VERSION="$PREFIX"
219
+ bash scripts/report-test-cycle.sh start \
220
+ --project-slug "$PROJECT_SLUG" --release "$VERSION" \
221
+ --sdlc-stage 5 --environment production --cycle-kind smoke \
222
+ --provider github_actions --external-run-id "$CI_RUN" \
223
+ --external-run-attempt "${{ github.run_attempt }}" --external-job-id "production-smoke" \
224
+ --idempotency-key "github:${{ github.repository }}:post-deploy-prod.smoke:${CI_RUN}:${{ github.run_attempt }}:5:${VERSION}" \
225
+ --commit-sha "$GIT_SHA" --branch main \
226
+ --workflow-name "Post-Deploy Production" \
227
+ --workflow-url "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
228
+ done
229
+
143
230
  - name: Production smoke tests (read-only)
231
+ id: production_smoke
232
+ if: steps.wait_deployment.outcome == 'success' && steps.host_deployment.outcome == 'success'
144
233
  run: |
145
234
  echo "=== Production Smoke Tests ==="
146
235
  HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "${PROD_URL}/")
@@ -163,8 +252,43 @@ jobs:
163
252
  }
164
253
  RESULTS_EOF
165
254
 
255
+ - name: Complete production smoke cycles
256
+ if: always() && env.BASE != '' && steps.host_deployment.outcome == 'success'
257
+ run: |
258
+ case "${{ steps.production_smoke.outcome }}" in
259
+ success) OUTCOME=passed; CHECK_STATUS=successful ;;
260
+ cancelled) OUTCOME=cancelled; CHECK_STATUS=cancelled ;;
261
+ skipped) OUTCOME=skipped; CHECK_STATUS=skipped ;;
262
+ *) OUTCOME=failed; CHECK_STATUS=failed ;;
263
+ esac
264
+ chmod +x scripts/report-test-cycle.sh scripts/report-release-check.sh 2>/dev/null || true
265
+ for PREFIX in ${REQS}; do
266
+ RESP=$(curl -fsS -H "Authorization: Bearer ${DEVAUDIT_API_KEY}" \
267
+ "${BASE}/api/ci/releases/resolve?projectSlug=${PROJECT_SLUG}&versionPrefix=${PREFIX}")
268
+ VERSION=$(echo "$RESP" | jq -r '.latest.version // empty')
269
+ [ -n "$VERSION" ] || VERSION="$PREFIX"
270
+ bash scripts/report-test-cycle.sh complete \
271
+ --project-slug "$PROJECT_SLUG" --release "$VERSION" \
272
+ --sdlc-stage 5 --environment production --cycle-kind smoke \
273
+ --provider github_actions --external-run-id "$CI_RUN" \
274
+ --external-run-attempt "${{ github.run_attempt }}" --external-job-id "production-smoke" \
275
+ --idempotency-key "github:${{ github.repository }}:post-deploy-prod.smoke:${CI_RUN}:${{ github.run_attempt }}:5:${VERSION}" \
276
+ --commit-sha "$GIT_SHA" --branch main \
277
+ --workflow-name "Post-Deploy Production" \
278
+ --workflow-url "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
279
+ --outcome "$OUTCOME" --outcome-reason "production smoke: ${{ steps.production_smoke.outcome }}"
280
+ bash scripts/report-release-check.sh \
281
+ --project-slug "$PROJECT_SLUG" --release "$VERSION" \
282
+ --check-key "production-smoke:${CI_RUN}:${{ github.run_attempt }}" \
283
+ --label "Production Smoke" --provider github_actions --status "$CHECK_STATUS" \
284
+ --external-run-id "$CI_RUN" \
285
+ --external-url "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
286
+ --commit-sha "$GIT_SHA" --branch main \
287
+ --details-json '{"executionSource":"steps.production_smoke.outcome"}'
288
+ done
289
+
166
290
  - name: File incident on smoke failure
167
- if: failure()
291
+ if: steps.production_smoke.outcome == 'failure'
168
292
  env:
169
293
  # GitHub issue/label mutations use the workflow token. DevAudit
170
294
  # user tokens are portal PATs, not guaranteed GitHub PATs (#305).
@@ -241,9 +365,11 @@ jobs:
241
365
  fi
242
366
 
243
367
  - name: Promote in-scope releases (evidence + status)
368
+ if: steps.production_smoke.outcome == 'success'
244
369
  run: |
245
- chmod +x scripts/upload-evidence.sh scripts/report-test-cycle.sh 2>/dev/null || true
370
+ chmod +x scripts/upload-evidence.sh scripts/report-test-cycle.sh scripts/report-release-check.sh 2>/dev/null || true
246
371
  PROMOTED=0
372
+ EVIDENCE_FAILURES=0
247
373
  for PREFIX in ${REQS}; do
248
374
  echo "=== Promoting ${PREFIX} ==="
249
375
  RESP=$(curl -s -H "Authorization: Bearer ${DEVAUDIT_API_KEY}" \
@@ -263,6 +389,7 @@ jobs:
263
389
  --provider github_actions \
264
390
  --external-run-id "${CI_RUN}" \
265
391
  --external-run-attempt "${{ github.run_attempt }}" \
392
+ --external-job-id "production-smoke" \
266
393
  --idempotency-key "github:${{ github.repository }}:post-deploy-prod.smoke:${CI_RUN}:${{ github.run_attempt }}:5:${VERSION}" \
267
394
  --commit-sha "${GIT_SHA}" \
268
395
  --branch main \
@@ -296,31 +423,28 @@ jobs:
296
423
  "${PROJECT_SLUG}" "${VERSION}" release_ticket "$TICKET" \
297
424
  --release "${VERSION}" --create-release-if-missing --environment production \
298
425
  --category release_artifact --sdlc-stage 5 --git-sha "${GIT_SHA}" --ci-run-id "${CI_RUN}" --branch main \
299
- || echo "Warning: ticket upload failed for ${VERSION}"
426
+ || { echo "Warning: ticket upload failed for ${VERSION}"; REQ_FAILURES=$((REQ_FAILURES + 1)); }
300
427
  else
301
428
  echo "No RELEASE-TICKET-${VERSION}.md found — skipping ticket (date-versioned or archived)."
302
429
  fi
303
430
  if [ "$REQ_FAILURES" -gt 0 ]; then
304
- REQ_OUTCOME=failed
431
+ EVIDENCE_STATUS=failed
432
+ EVIDENCE_FAILURES=$((EVIDENCE_FAILURES + 1))
305
433
  else
306
- REQ_OUTCOME=passed
434
+ EVIDENCE_STATUS=successful
435
+ fi
436
+ bash scripts/report-release-check.sh \
437
+ --project-slug "$PROJECT_SLUG" --release "$VERSION" \
438
+ --check-key "production-evidence:${CI_RUN}:${{ github.run_attempt }}" \
439
+ --label "Production Evidence Completeness" --provider devaudit_installer \
440
+ --status "$EVIDENCE_STATUS" --external-run-id "$CI_RUN" \
441
+ --external-url "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
442
+ --commit-sha "$GIT_SHA" --branch main \
443
+ --details-json "{\"uploadFailures\":${REQ_FAILURES}}"
444
+ if [ "$REQ_FAILURES" -gt 0 ]; then
445
+ echo "::error::Skipping status promotion for ${VERSION}: production evidence is incomplete"
446
+ continue
307
447
  fi
308
- bash scripts/report-test-cycle.sh complete \
309
- --project-slug "${PROJECT_SLUG}" \
310
- --release "${VERSION}" \
311
- --sdlc-stage 5 \
312
- --environment production \
313
- --cycle-kind smoke \
314
- --provider github_actions \
315
- --external-run-id "${CI_RUN}" \
316
- --external-run-attempt "${{ github.run_attempt }}" \
317
- --idempotency-key "github:${{ github.repository }}:post-deploy-prod.smoke:${CI_RUN}:${{ github.run_attempt }}:5:${VERSION}" \
318
- --commit-sha "${GIT_SHA}" \
319
- --branch main \
320
- --workflow-name "Post-Deploy Production" \
321
- --workflow-url "${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
322
- --started-at "${cycle_started_at:-}" \
323
- --outcome "${REQ_OUTCOME}"
324
448
  # Advance status (idempotent — re-PATCHing an already-promoted release is a no-op).
325
449
  if [ -n "$RELEASE_ID" ]; then
326
450
  curl -s -o /dev/null -w " ${VERSION} status patch: HTTP %{http_code}\n" \
@@ -334,6 +458,10 @@ jobs:
334
458
  echo "::warning::No release_id resolved for ${PREFIX} — skipping status patch"
335
459
  fi
336
460
  done
461
+ if [ "$EVIDENCE_FAILURES" -gt 0 ]; then
462
+ echo "::error::${EVIDENCE_FAILURES} release(s) have incomplete production evidence"
463
+ exit 1
464
+ fi
337
465
  echo "Promoted ${PROMOTED} release(s) to ${TERMINAL_STATUS}."
338
466
  if [ "${TERMINAL_STATUS}" = "prod_review" ]; then
339
467
  echo "Next: a human in the portal clicks 'Approve Production' then 'Mark as Released' for each."
package/sdlc/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@metasession.co/devaudit-sdlc",
3
- "version": "0.3.13",
3
+ "version": "0.3.14",
4
4
  "description": "DevAudit SDLC CLI Engine — cross-agent terminal-driven SDLC orchestrator.",
5
5
  "bin": {
6
6
  "devaudit-sdlc": "./src/bin/devaudit-sdlc.js"